マシンがEC2インスタンスかどうかを知る方法


43

EC2インスタンスのホストでいくつかのスクリプトを実行したいのですが、ホストが本当に EC2インスタンスであることを確認する方法がわかりません。

私はいくつかのテストを行いましたが、これは十分ではありません:

  • バイナリーec2_userdataが使用可能であることをテストします(ただし、これは常に正しいとは限りません)
  • http://169.254.169.254/latest/meta-data」の可用性をテストします(ただし、これは常に真実ですか?この「魔法のIP」とは何ですか?)


これは実際にはAPIPAアドレスであり、メタデータ取得などの重要なサービスの参照として使用するのは非常に奇妙です。
マチューセルダ

2
EC2のIP範囲は公開されています(ただし、時々異なります)。現在のリストについていく場合は、その範囲に対してインスタンスIPを確認できます。
カルマFusebox

2
EC2とEC2 のみが必要な場合は、169.254.169.254に依存しないでください。EucalyptusなどのEC2に似たシステムでもサポートされています。engage.eucalyptus.com/customer/portal/articles/...
ceejayoz

1
ホストにルートがあり、自分の悪意のある目的のためにEC2インスタンスだと思わせるようになりすましている攻撃者に対して機能する方法が必要ですか?そうした場合、それははるかに困難になります。
マイクスコット

回答:


3

実際、ホストがEC2インスタンスであるかどうかを検出する非常に簡単な方法があります。パブリックIPの逆ルックアップを確認してください。EC2の反転は見逃しがたいものです。

また、変更しなかった場合は、ホスト名を逆にして、見つけやすくする必要があります。

実際にEC2インスタンスタグを取得する標準的な方法であるため、先ほど説明した「マジカルIP」を使用することもできますが、EC2ネットワーク上にいない場合は、一般的にはタイムアウトになるまで待つ必要があります。望ましい...

これらの方法で十分でない場合は、IPのwhoisを実行し、Amazon EC2 IPブロック内にいるかどうかを確認してください。

編集:この小さなシェルビットを使用することができます:

#!/bin/bash
LOCAL_HOSTNAME=$(hostname -d)
if [[ ${LOCAL_HOSTNAME} =~ .*\.amazonaws\.com ]]
then
        echo "This is an EC2 instance"
else
        echo "This is not an EC2 instance, or a reverse-customized one"
fi

ただし、[[はバシズムです。PythonまたはPerlユニライン、YMMVを使用することもできます。


13
これは、VPCまたはホスト名を変更した環境では機能しません。例えば。あなたのマシンがdomain.localである場合
Preflightsiren

2
ホスト名ビットは失敗するだけです。
ダンプリッツ14

3
hostname -dリターンeu-west-1.compute.internal
Bulletmagnet

42

Hannesの回答を変更して、エラーメッセージを回避し、スクリプトでの使用例を含めました。

if [ -f /sys/hypervisor/uuid ] && [ `head -c 3 /sys/hypervisor/uuid` == ec2 ]; then
    echo yes
else
    echo no
fi

これは、Windowsインスタンスでは機能しません。カールに対する利点は、EC2と非EC2の両方で瞬時に近いことです。


4
AWSはまた、このようにそれやってお勧めしているように見えるdocs.aws.amazon.com/AWSEC2/latest/UserGuide/...
マイク・

3
私はこの方法が好きです。ハイパーバイザーの下で実行されている非EC2システムは、次で始まるUUIDを生成する可能性があることに注意してくださいec2-誤検知。その可能性は低く(256分の1の可能性)、そのファイルを取り込むハイパーバイザーを使用している場合のみです。上記のリンクのドキュメントに「おそらく EC2インスタンスを見ている」と書かれている理由です。
ネイト

1
@ネイト、良い点ですが、それは4096分の1のチャンスではないでしょうか?(16 x 16 x 16)
ワイルドカード

2
@Wildcard:コメントを編集することはできませんが、そうです。
ネイト

7
危険!この方法は何年もの間、私たちにとって確実に機能していました...ごく最近まで、このファイルが存在しない最新のc5およびm5タイプでした。したがって、これらのインスタンスを処理するには、169.254.169.254のフォールバックチェックを追加する必要があります。
ジョシュKupershmidt

20

まず、既存の回答に関する次の微妙な問題のため、および@qwertzguyの回答に関する私のコメントについて質問を受けた後、新しい回答を投稿する必要があると感じました。現在の回答の問題は次のとおりです。

  1. 受け入れ答え @MatthieuCerdaからは間違いなく、少なくともではない私はと照合任意のVPCインスタンス上で、確実に動作しません。(私のインスタンスhostname -dでは、「amazonaws.com」が含まれているものではなく、内部DNSに使用されるのVPC名を取得します。)
  2. @qwertzguyからの最高投票数の回答は、このファイルを持たない新しいm5またはc5インスタンスでは機能しません。けれども、この動作の変更私の知る限りを文書化するために無視アマゾンドキュメントページこのテーマには言ってない「... 場合は / SYS /ハイパーバイザー/ UUIDが存在し...」。この変更が意図的なものであるかどうかをAWSサポートに尋ねました。以下を参照してください†。
  3. DNSルックアップが機能しない可能性があるため、@ Jerから回答は必ずしもどこでも機能するわけではありませんinstance-data.ec2.internal。私がテストしたばかりのUbuntu EC2 VPCインスタンス $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal では、このメソッドに依存するコードがEC2にないという誤った結論を下す原因となります。
  4. 使用に対する答えdmidecode @tamaleからは動作しますが、あなたに依存していることがあります。)を有するdmidecode、あなたのインスタンスで利用できると、b。)rootまたは持つsudoあなたのコード内からパスワードなしの能力を。
  5. / SYS /デバイス/仮想/ DMI / ID / bios_versionをチェックするための答え @spkaneからは危険な誤解です!私は1つのUbuntu 14.04 M5インスタンスをチェックし、得たbios_version1.0。このファイルはAmazonのドキュメントにはまったく記載されていませんので、私は実際にはそれに依存しません。
  6. @ Chris-Montanaroから回答の最初の部分は、信頼できないサードパーティのURLをチェックwhoisし、その結果を使用することは、いくつかのレベルで問題があります。その回答で提案されているURLは、現在404ページです!動作するサードパーティのサービスを見つけたとしても、(ローカルでファイルをチェックするのに比べて)比較的非常に遅く、レート制限の問題やネットワークの問題が発生する可能性があります。外部ネットワークアクセス。
  7. http://169.254.169.254/をチェックするための@ Chris-Montanaroから回答の2番目の提案は少し優れていますが、別のコメント提供者は、他のクラウドプロバイダーがこのインスタンスメタデータURLを利用可能にしているので、falseを避けるように注意する必要がありますポジティブ。また、ローカルファイルよりもはるかに遅くなります。負荷の高いインスタンスでは、このチェックが特に遅い(戻るのに数秒かかる)のを見てきました。また、あなたが渡すために覚えておく必要がある-mか、--max-time特にこのアドレスはどこにつながると(のようにハングアップすることが非EC2インスタンス上で、非常に長い時間のためにぶら下げ、それを避けるために、カールの引数を@藻類の答え)。

また、(可能性のある)ファイルをチェックするというAmazonの文書化されたフォールバックについて誰も言及していないようです/sys/devices/virtual/dmi/id/product_uuid

EC2で実行しているかどうかを判断するのが非常に複雑になることを誰が知っていましたか?!リストされたアプローチの(ほとんどの)問題がリストされているので、EC2で実行しているかどうかを確認するための推奨bashスニペットを次に示します。これは、ほぼすべてのLinuxインスタンスで一般的に機能するはずだと思います。Windowsインスタンスは読者にとっての演習です。

#!/bin/bash

# This first, simple check will work for many older instance types.
if [ -f /sys/hypervisor/uuid ]; then
  # File should be readable by non-root users.
  if [ `head -c 3 /sys/hypervisor/uuid` == "ec2" ]; then
    echo yes
  else
    echo no
  fi

# This check will work on newer m5/c5 instances, but only if you have root!
elif [ -r /sys/devices/virtual/dmi/id/product_uuid ]; then
  # If the file exists AND is readable by us, we can rely on it.
  if [ `head -c 3 /sys/devices/virtual/dmi/id/product_uuid` == "EC2" ]; then
    echo yes
  else
    echo no
  fi

else
  # Fallback check of http://169.254.169.254/. If we wanted to be REALLY
  # authoritative, we could follow Amazon's suggestions for cryptographically
  # verifying their signature, see here:
  #    https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
  # but this is almost certainly overkill for this purpose (and the above
  # checks of "EC2" prefixes have a higher false positive potential, anyway).
  if $(curl -s -m 5 http://169.254.169.254/latest/dynamic/instance-identity/document | grep -q availabilityZone) ; then
    echo yes
  else
    echo no
  fi

fi

明らかに、さらに多くのフォールバックチェックでこれを拡張し、たとえば/sys/hypervisor/uuid偶然 "ec2"で始まる偶然の誤検出などの処理についての妄想を含めることができます。しかし、これは説明の目的のための十分なソリューションであり、おそらくほぼすべての非病理学的ユースケースです。

[†] c5 / m5インスタンスの変更に関するAWSサポートからのこの説明に戻りました。

C5およびM5インスタンスは新しいハイパーバイザースタック使用し、他の/古いインスタンスタイプで使用される Xenドライバーが行うように、関連するカーネルドライバーはsysfs(/ sysにマウントされる)にファイルを作成しませ。オペレーティングシステムがEC2インスタンスで実行されているかどうかを検出する最良の方法は、リンクしたドキュメントに記載されているさまざまな可能性を考慮することです


4
はい、2018年の仲間の旅行者...これはあなたが探していた答えです。
ラッセルピアス

/ sys / devices / virtual / dmi / id / product_uuidを読み取るにはルート権限も必要です
Thayne

@Thayne正しい-それelifが、そのブロックの上のコメントが言っていることであり、それelif-rテストがテスト演算子を使用する理由です。
ジョシュクペルシュミット

169.254.169.254メタデータに関する追加の注記-起動時に常に準備が整っているとは限りません。ブートスクリプトにそのメタデータが必要な場合は、準備が整うまでポーリングを続ける必要があります。インスタンスがcloud-initブートスクリプトの実行を開始してから最大30秒かかります。
vacri

15

IPではなくEC2内部ドメイン名でメタデータを探します。これにより、EC2を使用していない場合に高速DNSエラーが返され、IPの競合やルーティングの問題が回避されます。

curl -s http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"

一部のディストリビューションでは、非常に基本的なシステム、またはインストールの非常に早い段階でcurlを使用できません。代わりにwgetを使用します。

wget -q http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"

4
残念ながら、VPCで失敗するようです!
アッシュ

2
また、二重引用符の内側に感嘆符文字を使用しないでください-あなたのエコーが爆破こと-bash: !": event not foundecho代わりに、これらのs に対して一重引用符を使用してください。
ジョシュKupershmidt

1
これはおそらく、サーバーがまだec2.internalゾーンを知っているEC2s DNSサーバーを使用しており、誰も/etc/resolv.confを8.8.8.8に変更していないか、独自のDNSインフラストラクチャを展開していないことを前提としています。
ラモント

1
AWSはこれを破ったようです。instance-data.ec2.internalを解決できなくなりました。ただし、少なくとも現時点では、instance-data.us-west-2.compute.internalは機能します。
ブライアンラーセン

14

目標がEC2インスタンスか、googleのような別の種類のクラウドインスタンスかを判断することである場合、dmidecode非常にうまく機能し、ネットワークは必要ありません。メタデータのURLパスがEC2とGCEで異なるため、このアプローチと他のアプローチのいくつかが好きです。

# From a google compute VM
$ sudo dmidecode -s bios-version
Google

# From an amazon ec2 VM
$ sudo dmidecode -s bios-version
4.2.amazon

私は他のVM環境での作業の罰金にしても、実際のハードウェア上でこれを期待したい-私は任意のハードウェアベンダーは、BIOSのバージョンが「アマゾン」は言うシステムを出荷することを期待しないでください...
GUSS

私のUbuntu EC2インスタンスでは、これが返されます1.0-の言及はありませんamazon
ネイト

5

ホスト名は変更される可能性が高いため、パブリックIPに対してwhoisを実行します。

if [[ ! -z $(whois $(curl -s shtuff.it/myip/short) | grep -i amazon) ]]; then 
  echo "I'm Amazon"
else 
  echo "I'm not Amazon"
fi

またはAWSメタデータURLをヒット

if [[ ! -z $(curl -s http://169.254.169.254/1.0/) ]]; then 
  echo "I'm Amazon"
else 
  echo "I'm not Amazon"
fi

2
--connect-timeout 1を2番目のcurlステートメントに追加して、EC2で実行していない場合にすぐに失敗するようにします。
ジョナサンオリバー

1
FWIWは、メタデータURLを使用して、クラウドインスタンスとして実行されていることを示すことができますが、特にEC2であるかどうかを最終的に判断することはできません。OpenStackとEucalyptusも同じメタデータURIを使用します。私はこれが非常に重要であることを知っていますが、私の仕事にとってはクラウドプロバイダーが重要です。
EmmEff 14

5

これはec2のLinuxホストでもうまく機能し、ネットワークおよび関連するタイムアウトを必要としません。

grep -q amazon /sys/devices/virtual/dmi/id/bios_version

Amazonはこのエントリを次のように定義しているため、これは機能します。

$ cat /sys/devices/virtual/dmi/id/bios_version 4.2.amazon


2018-05-01; Ubuntuを実行しているM5インスタンスでは無効のようです。
ラッセルピアス

私のUbuntu EC2インスタンスでは、これが返されます1.0。の言及はありませんamazon
ネイト

3
test -f /sys/hypervisor/uuid -a `head -c 3 /sys/hypervisor/uuid` == ec2 && echo yes

しかし、これがディストリビューション間でどれほど移植性があるかはわかりません。


2
確かに、Windows EC2インスタンスでは動作しません。
ceejayoz

1
この方法は、あらゆる種類の理由でハングアップする可能性のあるネットワーク相互作用を伴わないため、この方法を好みます。HTTP交換にタイムアウトを使用しても、ハングを防ぐことは保証されません。Windowsインスタンスは気にしません。
ハネス

それがまさに私が必要としたものです!何かをカールするよりはましだ、ありがとう!
qwertzguy

1
他のベンダーのハイパーバイザーUUIDも「ec2」で始まる場合に備えて、完全なUUIDの使用を検討してください。その可能性は4096分の1であり、無視できません。
ハネス

1
実際、複数の異なるハイパーバイザーUUIDが実際に見られているため、UUID全体を比較することはできません。ただし、すべて「ec2」で始まるため、この答えはそのまま機能します。
ハネス

3

素早い回答:

if [[ -f /sys/devices/virtual/dmi/id/product_uuid ]] && \
    grep -q "^EC2" /sys/devices/virtual/dmi/id/product_uuid
then
    echo "IS EC2"
else
    echo "NOT EC2"
fi

私はここに投稿された回答の1つを1年以上使用していましたが、新しい「c5」インスタンスタイプでは機能しません(現在「c4」からのアップグレードに取り組んでいます)。

このソリューションが好きなのは、将来的に壊れる可能性が最も低いと思われるからです。

古いインスタンスタイプと新しいインスタンスタイプでは、このファイルが存在し、「EC2」で始まります。VirtualBoxで実行されているUbuntuをチェックし(これもサポートする必要がある)、文字列「VirtualBox」が含まれています。

前のポスターに書かれているように(しかし見逃しがちだった)-これを行う方法に関するAmazonのドキュメントがあります-私の答えが含まれています。

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html


2

おそらく、「facter」を使用できます。

「Facterは、オペレーティングシステム、Linuxディストリビューション、MACアドレスなど、シンプルなオペレーティングシステムのファクトを取得するためのクロスプラットフォームライブラリです。」

http://www.puppetlabs.com/puppet/related-projects/facter/

たとえば、ec2ファクト(facter-1.6.12 / lib / facter / ec2.rb)を見てみると:

require 'facter/util/ec2'
require 'open-uri'

def metadata(id = "")
  open("http://169.254.169.254/2008-02-01/meta-data/#{id||=''}").read.
    split("\n").each do |o|
    key = "#{id}#{o.gsub(/\=.*$/, '/')}"
    if key[-1..-1] != '/'
      value = open("http://169.254.169.254/2008-02-01/meta-data/#{key}").read.
        split("\n")
      symbol = "ec2_#{key.gsub(/\-|\//, '_')}".to_sym
      Facter.add(symbol) { setcode { value.join(',') } }
    else
      metadata(key)
    end
  end
end

def userdata()
  begin
    value = open("http://169.254.169.254/2008-02-01/user-data/").read.split
    Facter.add(:ec2_userdata) { setcode { value } }
  rescue OpenURI::HTTPError
  end
end

if (Facter::Util::EC2.has_euca_mac? || Facter::Util::EC2.has_openstack_mac? ||
    Facter::Util::EC2.has_ec2_arp?) && Facter::Util::EC2.can_connect?

  metadata
  userdata
else
  Facter.debug "Not an EC2 host"
end

1

curlがインストールされている場合、EC2内で実行している場合、このコマンドは0を返し、そうでない場合は0以外を返します。

curl --max-time 3 http://169.254.169.254/latest/meta-data/ami-id 2>/dev/null 1>/dev/null`

AMI-IDを宣言するEC2メタデータをプルしようとします。3秒後にこれが成功しない場合、EC2で実行されていないと見なされます。


0

このパーティーに少し遅れましたが、この投稿に出会い、AWSのドキュメントを見つけました。

EC2インスタンスを特定する決定的かつ暗号で検証された方法については、署名を含むインスタンスIDドキュメントを確認してください。これらのドキュメントは、ローカルのルーティング不可能なアドレスhttp://169.254.169.254/latest/dynamic/instance-identity/のすべてのEC2インスタンスで利用可能です

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html

もちろん、次のようにカールタイムアウトを設定できますが、これにはネットワークオーバーヘッドが必要です。

curl -s --connect-timeout 5 http://169.254.169.254/latest/dynamic/instance-identity/

これにより、タイムアウトが5秒に設定されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.