Frage Wie kann man feststellen, ob eine Maschine eine EC2-Instanz ist?


Ich möchte einige Skripte auf Hosts ausführen, die EC2-Instanzen sind, aber ich weiß nicht, wie ich sicher sein kann, dass der Host dies ist Ja wirklich eine EC2-Instanz.

Ich habe einige Tests gemacht, aber das ist nicht ausreichend:

  • Testen Sie, dass die binäre ec2_userdata verfügbar ist (aber das wird nicht immer wahr sein)
  • Test Verfügbarkeit von "http://169.254.169.254/latest/meta-data"(Aber wird das immer wahr sein? und was ist das" magische IP "?)

39
2018-01-04 09:12


Ursprung


169.254.0.0/16 ist der "link local" -Block. - Charles
Es ist tatsächlich eine APIPA-Adresse, die ziemlich seltsam ist, als eine Referenz für einen kritischen Dienst wie Metadatenabruf zu verwenden. - Matthieu Cerda
Die IP-Bereiche von EC2s sind öffentlich (obwohl sie von Zeit zu Zeit variieren). Wenn Sie mit einer aktuellen Liste Schritt halten, können Sie die IP der Instanzen mit diesen Bereichen überprüfen. - Karma Fusebox
Verlassen Sie sich nicht auf 169.254.169.254, wenn Sie EC2 und nur EC2 - EC2-ähnliche Systeme wie Eucalyptus unterstützen es ebenfalls. engagement.eucalyptus.com/customer/portal/articles/... - ceejayoz
Brauchen Sie die Methode, um gegen einen Angreifer zu arbeiten, der Root auf dem Host hat und versucht, Sie dazu zu bringen, zu denken, dass es eine EC2-Instanz für seine eigenen bösartigen Zwecke ist? Wenn Sie das tun, wird es viel schwieriger. - Mike Scott


Antworten:


Nun, es gibt eine sehr einfache Möglichkeit zu erkennen, ob der Host eine EC2-Instanz ist: Überprüfen Sie das Reverse-Lookup Ihrer öffentlichen IP-Adresse. Die EC2-Rückschläge sind ziemlich schwer zu übersehen.

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

Sie können auch die "magische IP" verwenden, über die Sie gesprochen haben, da dies in der Tat der Standard ist, um EC2 Instance-Tags zu erhalten. Wenn Sie jedoch nicht in einem EC2-Netzwerk sind, müssen Sie auf eine Zeitüberschreitung warten wünschenswert...

Wenn diese Methoden nicht ausreichen, machen Sie einfach einen Whois Ihrer IP und prüfen Sie, ob Sie innerhalb und Amazon EC2 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

Vorsichtig aber [[ist ein Bashismus. Sie können auch ein Python oder Perl uniline YMMV verwenden.


3
2018-01-04 09:20



Dies funktioniert nicht in einer VPC oder einer Umgebung, in der Sie den Hostnamen geändert haben. z.B. Wenn sich Ihre Maschinen in domain.local befinden - Preflightsiren
Das Hostname-Bit ist nur zum Scheitern verurteilt. - Dan Pritts
hostname -d kehrt zurück eu-west-1.compute.internal - Bulletmagnet


Hannes 'Antwort wurde geändert, um Fehlermeldungen zu vermeiden und die Beispielverwendung im Skript einzuschließen:

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 Curl ist, dass es sowohl bei EC2 als auch bei Nicht-EC2 kurzzeitig ist.


37
2018-06-22 18:36



AWS scheint es auch so zu empfehlen docs.aws.amazon.com/AWSEC2/latest/UserGuide/... - Mike
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 ec2 - ein falsches positives Ergebnis Es ist unwahrscheinlich (eine 1-in-256-Chance) und nur, wenn Sie einen Hypervisor verwenden, der diese Datei auffüllt. Deshalb sagt die oben verlinkte Dokumentation: "Du bist wahrscheinlich Blick auf eine EC2-Instanz ". - Nate
@Nate, guter Punkt, aber sollte das nicht eine 1 in 4096 Chance sein? (16 x 16 x 16) - Wildcard
@Wildcard: Ich kann meinen Kommentar nicht bearbeiten, aber das stimmt. - Nate
ACHTUNG! Diese Methode hat uns jahrelang zuverlässig geholfen ... bis vor kurzem mit den neuesten c5 und m5 Typen Habe diese Datei nicht vorhanden. Also muss ich einen Fallback-Check von hinzufügen 169.254.169.254 um diese Instanzen zu behandeln. - Josh Kupershmidt


Suchen Sie nach den Metadaten nach dem internen Domänennamen der EC2 anstelle von IP, wodurch ein schneller DNS-Fehler zurückgegeben wird, wenn Sie nicht auf EC2 sind, und IP-Konflikte oder Routingprobleme vermieden werden:

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

Auf einigen Distributionen, sehr einfachen Systemen oder sehr früh in Installationsphasen locken ist nicht verfügbar. Verwenden wget stattdessen:

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

16
2018-02-13 18:41



Leider scheint in VPC fehlzuschlagen! - Ashe
Verwenden Sie auch nicht das Ausrufezeichen in doppelten Anführungszeichen - Ihr Echo kann explodieren mit -bash: !": event not found. Verwenden Sie einfache Anführungszeichen für diese echos stattdessen. - Josh Kupershmidt
Dies setzt vermutlich voraus, dass der Server immer noch EC2s DNS-Server verwendet, die von der Zone ec2.internal wissen und dass niemand /etc/resolv.conf auf 8.8.8.8 geändert hat oder eine eigene DNS-Infrastruktur aufgebaut hat. - lamont
AWS scheint dies gebrochen zu haben. Ich kann instance-data.ec2.internal nicht mehr auflösen. instance-data.us-west-2.compute.internal funktioniert, zumindest für den Moment. - Bryan Larsen


Wenn das Ziel ist zu sagen, ob es eine EC2-Instanz oder eine andere Art von Cloud-Instanz ist, wie Google, dann dmidecode funktioniert sehr gut und keine Vernetzung ist erforderlich. Ich mag dies gegenüber einigen anderen Ansätzen, weil 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

15
2018-05-05 16:02



Ich würde erwarten, dass dies auch in anderen VM-Umgebungen und sogar auf echter Hardware gut funktioniert - ich erwarte nicht, dass Hardware-Hersteller Systeme ausliefern, auf denen die Bios-Version "amazon" heißt ... - Guss


Erstens hatte ich das Bedürfnis, eine neue Antwort zu schreiben, wegen der folgenden subtilen Probleme mit den vorhandenen Antworten und nachdem ich eine Frage über meine Antwort erhalten hatte Kommentar zu @ Qwertzguys Antwort. Hier sind die Probleme mit den aktuellen Antworten:

  1. Das akzeptierte Antwort von @MatthieuCerda funktioniert definitiv nicht zuverlässig, zumindest nicht auf irgendwelchen VPC-Instanzen, gegen die ich gecheckt habe. (Auf meinen Instanzen erhalte ich einen VPC-Namen für hostname -d, die für interne DNS verwendet wird, nichts mit "amazonaws.com" darin.)
  2. Das am meisten gewählte Antwort von @qwertzguy funktioniert nicht bei neuen m5- oder c5-Instanzen, die diese Datei nicht haben. Amazon vernachlässigt diese Verhaltensänderung AFAIK zu dokumentieren, obwohl die Dokumentseite zu diesem Thema sagt "... Ob / sys / hypervisor / uuid exists ... ". Ich habe AWS um Unterstützung gebeten, ob diese Änderung beabsichtigt war, siehe unten †.
  3. Das Antwort von @Jer funktioniert nicht unbedingt überall, weil der instance-data.ec2.internal DNS-Suche funktioniert möglicherweise nicht. Auf einer Ubuntu EC2 VPC-Instanz, die ich gerade getestet habe, sehe ich: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal was dazu führen würde, dass Code, der sich auf diese Methode stützt, fälschlicherweise zu dem Schluss kommt, dass er nicht auf EC2 ist!
  4. Das zu verwendende Antwort dmidecode von @tamale kann funktionieren, aber verlässt sich auf Sie a.) haben dmidecode verfügbar auf Ihrer Instanz und b.) mit root oder sudo Passwort-freie Fähigkeit aus Ihrem Code.
  5. Das antworte auf check / sys / devices / virtual / dmi / id / bios_version von @spkane ist gefährlich irreführend! Ich überprüfte eine Ubuntu 14.04 m5 Instanz und bekam eine bios_version von 1.0. Diese Datei ist überhaupt nicht dokumentiert auf Amazon doc, also würde ich mich wirklich nicht darauf verlassen.
  6. Der erste Teil des Antwort von @ Chris-Montanaro um eine unzuverlässige URL eines Drittanbieters zu überprüfen und zu verwenden whois auf das Ergebnis ist auf mehreren Ebenen problematisch. Beachten Sie, dass die in dieser Antwort vorgeschlagene URL eine 404-Seite ist! Selbst wenn Sie einen Drittanbieter-Dienst gefunden haben, der funktioniert, wäre es vergleichsweise sehr langsam (im Vergleich zur lokalen Prüfung einer Datei) und möglicherweise zu Problemen mit der Ratenbegrenzung oder zu Netzwerkproblemen führen oder Ihre EC2-Instanz möglicherweise nicht einmal über einen externen Netzwerkzugriff verfügt.
  7. Der zweite Vorschlag in der Antwort von @ Chris-Montanaro überprüfen http://169.254.169.254/ ist ein wenig besser, aber ein anderer Kommentator merkt an, dass andere Cloud-Anbieter diese Instanz-Metadaten-URL verfügbar machen, so dass Sie vorsichtig sein müssen, um falsche Positive zu vermeiden. Außerdem ist es immer noch viel langsamer als eine lokale Datei. Ich habe gesehen, dass diese Prüfung bei schwer belasteten Instanzen besonders langsam ist (mehrere Sekunden, um zurückzukehren). Außerdem sollten Sie daran denken, einen zu übergeben -m oder --max-time Argument zu curl, um zu vermeiden, dass es für eine sehr lange Zeit hängen bleibt, besonders auf einer Nicht-EC2-Instanz, wo diese Adresse ins Nirgendwo führen und hängen kann (wie in @algals Antwort).

Ich sehe auch nicht, dass irgendjemand es erwähnt hat Amazon ist dokumentiert Fallback der Überprüfung auf die (mögliche) Datei /sys/devices/virtual/dmi/id/product_uuid.

Wer hätte gedacht, dass die Entscheidung, ob Sie auf EC2 laufen, so kompliziert sein könnte ?! OK, jetzt, da wir (die meisten) Probleme mit aufgelisteten Ansätzen aufgelistet haben, ist hier ein vorgeschlagenes Bash-Snippet, um zu überprüfen, ob Sie auf EC2 laufen. 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

Natürlich könnte man dies mit noch mehr Fallback-Checks erweitern und Paranoia über die Handhabung z. ein falsches positives von /sys/hypervisor/uuid passiert zufällig mit "ec2" und so weiter. Aber das ist eine gut genug Lösung für Illustrationszwecke und wahrscheinlich fast alle nicht-pathologischen Anwendungsfälle.

[†] Bekomme diese Erklärung von der AWS-Unterstützung für die Änderung für c5 / m5-Instanzen zurück:

Die Instanzen C5 und M5 verwenden a neuer Hypervisor-Stack Die zugehörigen Kerneltreiber erstellen keine Dateien in sysfs (die unter / sys gemountet ist) als Xen-Treiber von den anderen / älteren Instanztypen verwendet werden. Der beste Weg, um zu erkennen, ob das Betriebssystem auf einer EC2-Instanz läuft, ist die Berücksichtigung der verschiedenen Möglichkeiten, die in der Dokumentation, die Sie verknüpft haben.


10
2018-03-20 14:46



Ja Mitreisender 2018 ... das ist die Antwort, nach der Sie gesucht haben. - russellpierce


Hostnamen werden sich wahrscheinlich ändern, führen Sie einen Whois gegen Ihre öffentliche IP 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 drücken Sie 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

5
2017-07-02 14:09



Fügen Sie ein --connect-timeout 1 zur zweiten curl-Anweisung hinzu, um schnell fehlzuschlagen, wenn Sie nicht auf EC2 laufen. - Jonathan Oliver
FWIW, unter Verwendung der Metadaten-URL können gibt an, dass es als Cloud-Instanz ausgeführt wird, kann jedoch nicht abschließend feststellen, ob es sich speziell um EC2 handelt. OpenStack und Eucalyptus verwenden ebenfalls denselben Metadaten-URI. Ich weiß, dass dies Nissen sind, aber für meine Arbeit, welcher Cloud-Anbieter zählt. - EmmEff


Dies funktioniert auch gut für Linux-Hosts in ec2 und erfordert nicht das Netzwerk und damit verbundene Timeouts:

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

Das funktioniert, weil Amazon diesen Eintrag so definiert:

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


5
2018-02-10 19:04



2018-05-01; scheint auf M5-Instanzen, auf denen Ubuntu ausgeführt wird, ungültig zu sein. - russellpierce


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

aber ich weiß nicht, wie tragbar das über Distributionen ist.


3
2018-06-04 03:18



Nun, es wird sicherlich nicht mit Windows EC2-Instanzen funktionieren. - ceejayoz
Ich bevorzuge diese Methode, da es keine Netzwerkinteraktion beinhaltet, die aus allen möglichen Gründen hängen kann. Die Verwendung von Zeitüberschreitungen für einen HTTP-Austausch verhindert nicht, dass ein Hängenbleiben verhindert wird. Ich interessiere mich nicht für Windows-Instanzen. - Hannes
Genau das habe ich gebraucht! Viel besser als etwas zu curlen, danke! - qwertzguy
Ziehen Sie die Verwendung der vollständigen UUID in Betracht, falls die UUID eines anderen Herstellers auch mit "ec2" beginnt. Die Chance dafür ist 1 in 4096, was nicht vernachlässigbar ist. - Hannes
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", also funktioniert diese Antwort wie sie ist. - Hannes


Vielleicht können Sie "facter" verwenden:

"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/

Betrachten wir beispielsweise die ec2-Tatsache (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

2
2018-01-04 16:06