Wie erkennt man, ob es sich bei einer Maschine um eine EC2-Instanz handelt?

43

Ich möchte einige Skripte auf Hosts ausführen, bei denen es sich um EC2-Instanzen handelt, kann aber nicht sicher sein, dass es sich bei dem Host tatsächlich um eine EC2-Instanz handelt.

Ich habe einige Tests gemacht, aber das reicht nicht aus:

  • Testen Sie, ob die Binärdatei ec2_userdata verfügbar ist (dies ist jedoch nicht immer der Fall).
  • Testverfügbarkeit von " http://169.254.169.254/latest/meta-data " (aber wird dies immer zutreffen? Und was ist diese "magische IP"?)
Kelindil
quelle
Eigentlich ist es eine APIPA-Adresse, die als Referenz für einen kritischen Dienst wie das Abrufen von Metadaten ziemlich seltsam ist.
Matthieu Cerda
2
Die IP-Bereiche von EC2s sind öffentlich (obwohl sie von Zeit zu Zeit variieren). Wenn Sie mit einer aktuellen Liste auf dem Laufenden bleiben, können Sie die IP-Adresse der Instanzen anhand dieser Bereiche überprüfen.
Karma Fusebox
2
Verlassen Sie sich nicht auf 169.254.169.254, wenn Sie EC2 und nur EC2 möchten - EC2-ähnliche Systeme wie Eucalyptus unterstützen dies ebenfalls. commit.eucalyptus.com/customer/portal/articles/…
ceejayoz
1
Benötigen Sie die Methode, um gegen einen Angreifer vorzugehen, der Root auf dem Host hat und versucht, Sie zu täuschen, dass es sich um eine EC2-Instanz für seine eigenen böswilligen Zwecke handelt? Wenn Sie dies tun, wird es viel schwieriger sein.
Mike Scott

Antworten:

3

Tatsächlich gibt es eine sehr einfache Möglichkeit, festzustellen, ob der Host eine EC2-Instanz ist: Überprüfen Sie die umgekehrte Suche Ihrer öffentlichen IP. Die EC2-Umkehrungen sind kaum zu übersehen.

Wenn Sie es nicht geändert haben, sollte der Hostname umgekehrt sein, damit Sie es leichter erkennen können.

Sie können auch die "magische IP" verwenden, von der Sie gesprochen haben, da dies in der Tat die Standardmethode zum Abrufen von EC2-Instanz-Tags ist. Wenn Sie sich jedoch nicht in einem EC2-Netzwerk befinden, müssen Sie auf eine Zeitüberschreitung warten, die in der Regel nicht der Fall ist wünschenswert...

Wenn diese Methoden nicht ausreichen, geben Sie einfach Ihre IP-Adresse ein und überprüfen Sie, ob Sie sich innerhalb von Amazon EC2 befinden und die IP blockieren.

EDIT: Sie können dieses kleine Shell-Bit verwenden:

#!/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

Vorsicht, [[ist ein Bashismus. Sie können auch eine Python- oder Perl-Uniline, YMMV, verwenden.

Matthieu Cerda
quelle
13
Dies funktioniert nicht in einer VPC oder einer Umgebung, in der Sie den Hostnamen geändert haben. z.B. Wenn Ihre Maschinen in domain.local sind
Preflightsiren
2
Das Hostname-Bit ist nur zum Fehlschlagen verpflichtet.
Dan Pritts
3
hostname -dkehrt zurückeu-west-1.compute.internal
Bulletmagnet
42

Die Antwort von Hannes wurde geändert, um Fehlermeldungen zu vermeiden und eine Beispielverwendung in das Skript aufzunehmen:

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

Dies funktioniert nicht in Windows-Instanzen. Vorteil gegenüber dem Einrollen ist, dass es sowohl bei EC2 als auch bei Nicht-EC2 nahezu augenblicklich ist.

Qwertzguy
quelle
4
AWS scheint auch zu empfehlen, dies auf diese Weise zu tun. Docs.aws.amazon.com/AWSEC2/latest/UserGuide/…
Mike
3
Ich mag diese Methode. Beachten Sie jedoch, dass ein Nicht-EC2-System, das unter einem Hypervisor ausgeführt wird, eine UUID generieren kann, die mit ec2einem falschen Positiv beginnt . Dies ist unwahrscheinlich (eine 1-in-256-Chance) und nur dann, wenn Sie einen Hypervisor verwenden, der diese Datei auffüllt. Aus diesem Grund heißt es in der oben verlinkten Dokumentation, dass es sich wahrscheinlich um eine EC2-Instanz handelt.
Nate
1
@Nate, guter Punkt, aber sollte das nicht eine 1 zu 4096 Chance sein? (16 x 16 x 16)
Wildcard
2
@Wildcard: Ich kann meinen Kommentar nicht bearbeiten, aber das stimmt.
Nate
7
ACHTUNG! Diese Methode hat jahrelang zuverlässig funktioniert ... bis vor kurzem mit den neuesten c5- und m5-Typen, bei denen diese Datei nicht vorhanden ist . Ich muss also eine Fallback-Prüfung von 169.254.169.254 hinzufügen , um diese Instanzen zu behandeln.
Josh Kupershmidt
20

Zuerst hatte ich das Bedürfnis, eine neue Antwort zu schreiben, weil die vorhandenen Antworten folgende subtile Probleme aufwiesen und nachdem ich eine Frage zu meinem Kommentar zur Antwort von @ qwertzguy erhalten hatte . Hier sind die Probleme mit den aktuellen Antworten:

  1. Die akzeptierte Antwort von @MatthieuCerda funktioniert definitiv nicht zuverlässig, zumindest nicht auf VPC-Instanzen, die ich überprüft habe. (Auf meinen Instanzen erhalte ich einen VPC-Namen für hostname -d, der für internes DNS verwendet wird, und nichts mit "amazonaws.com".)
  2. Die am höchsten bewertete Antwort von @qwertzguy funktioniert nicht auf neuen m5- oder c5-Instanzen , die diese Datei nicht haben. Amazon versäumt es, diese Verhaltensänderung AFAIK zu dokumentieren, obwohl auf der Dokumentseite zu diesem Thema "... If / sys / hypervisor / uuid exists ..." steht. Ich habe den AWS-Support gefragt, ob diese Änderung beabsichtigt ist, siehe unten †.
  3. Die Antwort von @Jer funktioniert nicht unbedingt überall, da die instance-data.ec2.internalDNS-Suche möglicherweise nicht funktioniert. Auf einer Ubuntu EC2 VPC-Instanz, auf der ich gerade getestet habe, sehe ich: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal Dies würde dazu führen, dass Code, der sich auf diese Methode stützt, fälschlicherweise zu dem Schluss kommt, dass es sich nicht um EC2 handelt!
  4. Die von @tamale zu verwendendedmidecode Antwort mag funktionieren, hängt jedoch davon ab, dass Sie a.) dmidecodeAuf Ihrer Instanz verfügbar sind und b.) Über Root- oder sudokennwortlose Funktionen in Ihrem Code verfügen .
  5. Die Antwort auf / sys / devices / virtual / dmi / id / bios_version von @spkane ist gefährlich irreführend! Ich habe eine Ubuntu 14.04 m5-Instanz überprüft und eine bios_versionvon 1.0. Diese Datei ist auf dem Amazon- Dokument überhaupt nicht dokumentiert , daher würde ich mich wirklich nicht darauf verlassen.
  6. Der erste Teil der Antwort von @ Chris-Montanaro zum Überprüfen einer unzuverlässigen Drittanbieter-URL und zum Verwenden whoisdes Ergebnisses ist auf mehreren Ebenen problematisch. Beachten Sie, dass die in dieser Antwort vorgeschlagene URL derzeit eine 404-Seite ist! Selbst wenn Sie einen 3rd-Party - Service finden taten der Arbeit getan hat, wäre es vergleichsweise seinen sehr langsam ( im Vergleich zu einer Datei lokal Überprüfung) und möglicherweise in geschwindigkeitsbegrenzenden Probleme oder Netzwerkprobleme führen, oder möglicherweise Ihre EC2 - Instanz noch nicht einmal außerhalb des Netzwerkzugriffs.
  7. Der zweite Vorschlag in der Antwort von @ Chris-Montanaro , http://169.254.169.254/ zu überprüfen, ist etwas besser, aber ein anderer Kommentator merkt an, dass andere Cloud-Anbieter diese Instanz-Metadaten-URL zur Verfügung stellen. Sie müssen also vorsichtig sein, um Falsches zu vermeiden Positive. Außerdem wird es immer noch viel langsamer als eine lokale Datei sein. Ich habe gesehen, dass diese Überprüfung bei stark belasteten Instanzen besonders langsam ist (mehrere Sekunden bis zur Rückkehr). Sie sollten auch daran denken, ein -moder ein --max-timeArgument an curl zu übergeben, um zu vermeiden, dass es sehr lange hängen bleibt, insbesondere in einer Nicht-EC2-Instanz, in der diese Adresse möglicherweise nirgendwohin führt und hängen bleibt (wie in der Antwort von @ algal ).

Ich sehe auch nicht, dass irgendjemand Amazon als dokumentierten Fallback für die Überprüfung der (möglichen) Datei erwähnt hat /sys/devices/virtual/dmi/id/product_uuid.

Wer hätte gedacht, dass die Entscheidung, ob Sie mit EC2 arbeiten, so kompliziert sein könnte ?! OK, jetzt, da wir (die meisten) Probleme mit den aufgelisteten Ansätzen haben, ist hier ein vorgeschlagenes Bash-Snippet, um zu überprüfen, ob Sie mit EC2 arbeiten. Ich denke, das sollte generell auf fast allen Linux-Instanzen funktionieren, Windows-Instanzen sind eine Übung für den Leser.

#!/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

Offensichtlich könnten Sie dies mit noch mehr Fallback-Checks erweitern und Paranoia über den Umgang mit z. B. einem /sys/hypervisor/uuidzufälligen Fehlalarm von "ec2" einschließen und so weiter. Dies ist jedoch eine ausreichend gute Lösung für Illustrationszwecke und wahrscheinlich für fast alle nicht-pathologischen Anwendungsfälle.

[†] Diese Erklärung zur Änderung für c5 / m5-Instanzen wurde vom AWS-Support zurückgegeben:

Die C5- und M5-Instanzen verwenden einen neuen Hypervisor-Stack, und die zugehörigen Kerneltreiber erstellen keine Dateien in sysfs (das unter / sys eingehängt ist) wie die Xen-Treiber, die von den anderen / älteren Instanztypen verwendet werden . Der beste Weg, um festzustellen, ob das Betriebssystem auf einer EC2-Instanz ausgeführt wird, besteht darin, die verschiedenen Möglichkeiten zu berücksichtigen, die in der von Ihnen verknüpften Dokumentation aufgeführt sind .

Josh Kupershmidt
quelle
4
Ja, Mitreisender im Jahr 2018 ... das ist die Antwort, nach der Sie gesucht haben.
Russellpierce
Für das Lesen von / sys / devices / virtual / dmi / id / product_uuid sind ebenfalls Root-Berechtigungen erforderlich
Thayne
@Thayne richtig - das steht in dem Kommentar über diesem elifBlock, und deshalb elifverwendet der -rTest den Testoperator, der prüft, ob die Datei vorhanden ist und ob Sie Leseberechtigungen für die Datei haben.
Josh Kupershmidt
Ein zusätzlicher Hinweis zu den 169.254.169.254- Metadaten: Sie sind zum Startzeitpunkt nicht immer bereit. Wenn Sie diese Metadaten für ein Boot-Skript benötigen, müssen Sie die Abfrage so lange fortsetzen, bis sie fertig sind. Ich habe gesehen, dass es bis zu 30 Sekunden dauert, nachdem die Instanz ihre Cloud-Init-Boot-Skripte gestartet hat.
Urlaub
15

Suchen Sie nach den Metadaten anhand des internen Domänennamens von EC2 anstelle der IP-Adresse. Dies führt zu einem schnellen DNS-Fehler, wenn Sie nicht mit EC2 arbeiten, und vermeidet IP-Konflikte oder Routing-Probleme:

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

In einigen Distributionen, sehr einfachen Systemen oder in sehr frühen Installationsphasen ist Curl nicht verfügbar. Verwenden Sie stattdessen wget :

wget -q http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"
Jer
quelle
4
Scheint leider in VPC zu scheitern!
Ashe
2
Verwenden Sie auch nicht das Ausrufezeichen Zeichen in doppelten Anführungszeichen - Ihr Echo kann sprengen mit -bash: !": event not found. Verwenden Sie echostattdessen einfache Anführungszeichen .
Josh Kupershmidt
1
Dies setzt wahrscheinlich voraus, dass der Server immer noch EC2s-DNS-Server verwendet, die die ec2.internal-Zone kennen und dass niemand /etc/resolv.conf in 8.8.8.8 geändert oder seine eigene DNS-Infrastruktur gerollt hat.
Lamont
1
AWS scheint dies gebrochen zu haben. Ich kann instance-data.ec2.internal nicht mehr auflösen. instance-data.us-west-2.compute.internal funktioniert jedoch zumindest vorerst.
Bryan Larsen
14

Wenn Sie feststellen möchten, ob es sich um eine EC2-Instanz oder eine andere Art von Cloud-Instanz handelt, wie z. B. Google, dmidecodefunktioniert dies sehr gut und es ist kein Netzwerk erforderlich. Ich mag dies im Vergleich zu einigen anderen Ansätzen, da der Metadaten-URL-Pfad für EC2 und GCE unterschiedlich ist.

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

# From an amazon ec2 VM
$ sudo dmidecode -s bios-version
4.2.amazon
Tamale
quelle
Ich erwarte, dass dies in anderen VM-Umgebungen und sogar auf echter Hardware gut funktioniert. Ich erwarte nicht, dass Hardwareanbieter Systeme ausliefern, bei denen die BIOS-Version "amazon" lautet ...
Guss
Auf meinen Ubuntu EC2-Instanzen wird dies zurückgegeben 1.0- keine Erwähnung von amazon.
Nate
5

Hostnamen ändern sich wahrscheinlich. Führen Sie einen Whois gegen Ihre öffentliche IP-Adresse aus:

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

oder klicken Sie auf die AWS-Metadaten-URL

if [[ ! -z $(curl -s http://169.254.169.254/1.0/) ]]; then 
  echo "I'm Amazon"
else 
  echo "I'm not Amazon"
fi
Chris Montanaro
quelle
2
Fügen Sie der zweiten curl-Anweisung ein --connect-timeout 1 hinzu, damit ein schneller Fehler auftritt, wenn Sie nicht mit EC2 arbeiten.
Jonathan Oliver
1
FWIW, die Metadaten URL kann zeigen , dass er als Cloud - Instanz läuft, kann aber nicht abschließend festzustellen , ob es speziell EC2 ist. OpenStack und Eucalyptus verwenden auch denselben Metadaten-URI. Ich weiß, dass dies Nissen sind, aber für meine Arbeit spielt der Cloud-Anbieter eine Rolle.
EmmEff
5

Dies funktioniert auch für Linux-Hosts in ec2 und erfordert kein Netzwerk und damit verbundene Zeitlimits:

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

Dies funktioniert, da Amazon diesen Eintrag folgendermaßen definiert:

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

spkane
quelle
2018-05-01; Scheint auf M5-Instanzen, auf denen Ubuntu ausgeführt wird, ungültig zu sein.
Russellpierce
Auf meinen Ubuntu EC2-Instanzen kommt dies zurück 1.0. Keine Erwähnung von amazon.
Nate
3
test -f /sys/hypervisor/uuid -a `head -c 3 /sys/hypervisor/uuid` == ec2 && echo yes

aber ich weiß nicht, wie portabel dies über Distributionen hinweg ist.

Hannes
quelle
2
Nun, auf Windows EC2-Instanzen wird es sicherlich nicht funktionieren.
Ceejayoz
1
Ich bevorzuge diese Methode, da es sich nicht um eine Netzwerkinteraktion handelt, die aus den unterschiedlichsten Gründen hängen bleiben kann. Die Verwendung von Zeitüberschreitungen für einen HTTP-Austausch kann nicht garantiert werden, um ein Hängenbleiben zu verhindern. Ich interessiere mich nicht für Windows-Instanzen.
Hannes
Genau das habe ich gebraucht! Viel besser als etwas zu kräuseln, danke!
Qwertzguy
1
Erwägen Sie die Verwendung der vollständigen UUID, falls die Hypervisor-UUID eines anderen Herstellers ebenfalls mit "ec2" beginnt. Die Wahrscheinlichkeit dafür ist 1 zu 4096, was nicht zu vernachlässigen ist.
Hannes
1
Tatsächlich funktioniert der Vergleich der gesamten UUID nicht, da ich mehrere verschiedene Hypervisor-UUIDs in freier Wildbahn gesehen habe. Sie beginnen alle mit "ec2", daher funktioniert diese Antwort so, wie sie ist.
Hannes
3

Schnelle Antwort:

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

Ich habe über ein Jahr lang eine der hier veröffentlichten Antworten verwendet - aber sie funktioniert nicht auf den neuen Instanztypen 'c5' (ich arbeite derzeit an einem Upgrade von 'c4').

Ich mag diese Lösung, weil es so scheint, als würde sie in Zukunft am wenigsten scheitern.

Bei den älteren und den neueren Instanztypen ist diese Datei vorhanden und beginnt mit 'EC2'. Ich habe geprüft, ob Ubuntu auf VirtualBox läuft (was ich auch unterstützen muss) und es enthält den String 'VirtualBox'.

Wie bereits in einem früheren Poster erwähnt (aber leicht zu übersehen), gibt es eine Amazon-Dokumentation, in der meine Antwort enthalten ist.

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

Zach Anthony
quelle
2

Vielleicht kannst du "facter" benutzen:

"Facter ist eine plattformübergreifende Bibliothek zum Abrufen einfacher Betriebssystemdaten wie Betriebssystem, Linux-Distribution oder MAC-Adresse."

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

Wenn wir uns zum Beispiel die ec2-Tatsache ansehen (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
jmprusi
quelle
1

Wenn Sie Curl installiert haben, gibt dieser Befehl 0 zurück, wenn Sie innerhalb von EC2 ausgeführt werden, und einen Wert ungleich Null, wenn Sie nicht:

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

Es wird versucht, die EC2-Metadaten abzurufen, in denen die AMI-ID deklariert ist. Wenn dies nach 3 Sekunden nicht gelingt, wird davon ausgegangen, dass EC2 nicht ausgeführt wird.

Algen
quelle
0

Ein bisschen zu spät zu dieser Party, aber ich bin auf diesen Beitrag gestoßen und habe dann diese AWS-Dokumentation gefunden:

Um eine endgültige und kryptografisch überprüfte Methode zur Identifizierung einer EC2-Instanz zu erhalten, überprüfen Sie das Instanzidentitätsdokument einschließlich seiner Signatur. Diese Dokumente sind auf jeder EC2-Instanz unter der lokalen, nicht routbaren Adresse http://169.254.169.254/latest/dynamic/instance-identity/ verfügbar.

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

Dies erfordert natürlich den Netzwerk-Overhead, obwohl Sie das Curl-Timeout wie folgt einstellen können:

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

Das setzt das Timeout auf 5s.

Brooks
quelle