Come sapere se una macchina è un'istanza EC2


43

Vorrei eseguire alcuni script su host che sono istanze EC2 ma non so come essere sicuro che l'host sia davvero un'istanza EC2.

Ho effettuato alcuni test, ma questo non è sufficiente:

  • Verifica che sia disponibile binario ec2_userdata (ma questo non sarà sempre vero)
  • Verifica la disponibilità di " http://169.254.169.254/latest/meta-data " (ma sarà sempre vero? E che cos'è questo "IP magico"?)


In realtà è un indirizzo APIPA, che è piuttosto strano da usare come riferimento per un servizio critico come il recupero dei metadati.
Matthieu Cerda,

2
Le gamme IP di EC2 sono pubbliche (anche se variano di volta in volta). Se si tiene il passo con un elenco corrente, è possibile verificare l'IP delle istanze rispetto a tali intervalli.
Karma Fusebox

2
Non fare affidamento su 169.254.169.254 se si desidera EC2 e solo EC2 - sistemi simili a EC2 come Eucalyptus lo supportano. engagement.eucalyptus.com/customer/portal/articles/…
ceejayoz

1
Hai bisogno del metodo per lavorare contro un utente malintenzionato che ha il root sull'host e sta cercando di farti credere di essere un'istanza EC2 per i suoi scopi maliziosi? Se lo fai, allora sarà molto più difficile.
Mike Scott,

Risposte:


3

Bene, in realtà esiste un modo molto semplice per rilevare se l'host è un'istanza EC2: controlla la ricerca inversa del tuo IP pubblico. I rovesci EC2 sono abbastanza difficili da perdere.

Inoltre, se non lo hai modificato, il nome host dovrebbe essere il tuo contrario, rendendo più facile individuarlo.

Potresti anche usare l '"IP magico" di cui hai parlato, dato che è davvero il modo standard per ottenere i tag dell'istanza EC2, tuttavia, se non sei su una rete EC2, dovrai aspettare un timeout, che generalmente non è desiderabile...

Se questi metodi non bastano, fai semplicemente un whois del tuo IP e controlla se ti trovi all'interno del blocco IP Amazon EC2.

EDIT: puoi usare questo piccolo bit shell:

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

Attento però, [[è un bashismo. Puoi anche usare un Python o Perl uniline, YMMV.


13
questo non funziona in un VPC o in un ambiente in cui è stato modificato il nome host; per esempio. se le tue macchine sono in domain.local
Preflightsiren,

2
il bit del nome host è destinato a fallire.
Dan Pritts,

3
hostname -dritornaeu-west-1.compute.internal
Bulletmagnet il

42

Modificata la risposta di Hannes per evitare messaggi di errore e includere esempi di utilizzo nello script:

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

Questo non funziona nelle istanze di Windows. Il vantaggio rispetto all'arricciatura è che è quasi istantaneo su EC2 e non EC2.


4
AWS sembra anche raccomandare di farlo in questo modo docs.aws.amazon.com/AWSEC2/latest/UserGuide/…
Mike,

3
Mi piace questo metodo Basta essere consapevoli del fatto che un sistema non EC2 in esecuzione sotto un hypervisor potrebbe generare un UUID che inizia con ec2un falso positivo. È improbabile (una possibilità 1 su 256) e solo se si utilizza un hypervisor che popola quel file. Ecco perché la documentazione collegata sopra dice " probabilmente stai guardando un'istanza EC2".
Nate,

1
@Nate, buon punto, ma non dovrebbe essere una possibilità 1 su 4096? (16 x 16 x 16)
Wildcard il

2
@Wildcard: non riesco a modificare il mio commento, ma è vero.
Nate,

7
PERICOLO! Questo metodo ha funzionato in modo affidabile per noi per anni ... fino a poco tempo fa, con gli ultimi tipi di c5 e m5 che non hanno questo file presente . Quindi devo aggiungere un controllo di fallback di 169.254.169.254 per gestire quelle istanze.
Josh Kupershmidt,

20

Innanzitutto, ho sentito la necessità di pubblicare una nuova risposta a causa dei seguenti sottili problemi con le risposte esistenti e dopo aver ricevuto una domanda sul mio commento sulla risposta di @ qwertzguy . Ecco i problemi con le risposte attuali:

  1. La risposta accettata da @MatthieuCerda sicuramente non funziona in modo affidabile, almeno non su tutte le istanze VPC che ho verificato. (Nei miei casi, ottengo un nome VPC per hostname -d, che viene utilizzato per il DNS interno, non nulla con "amazonaws.com" in esso.)
  2. La risposta più votata da @qwertzguy non funziona su nuove istanze m5 o c5 , che non dispongono di questo file. Amazon trascura di documentare questo cambiamento di comportamento AFAIK, sebbene la pagina del documento su questo argomento reciti "... Se esiste / sys / hypervisor / uuid ...". Ho chiesto al supporto AWS se questo cambiamento fosse intenzionale, vedi sotto †.
  3. La risposta di @Jer non funziona necessariamente ovunque perché la instance-data.ec2.internalricerca DNS potrebbe non funzionare. Su un'istanza VPC di Ubuntu EC2 che ho appena testato, vedo: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal ciò causerebbe la conclusione errata del codice basato su questo metodo che non si trova su EC2!
  4. La risposta da utilizzaredmidecode da @tamale può funzionare, ma si basa sul fatto che a.) Disponendo della dmidecodepropria istanza e b.) Con capacità root o senza sudopassword all'interno del proprio codice.
  5. La risposta a check / sys / devices / virtual / dmi / id / bios_version di @spkane è pericolosamente fuorviante! Ho controllato un'Ubuntu 14.04 esempio m5, e ottenuto un bios_versiondi 1.0. Questo file non è affatto documentato sul documento di Amazon , quindi non vorrei davvero fare affidamento su di esso.
  6. La prima parte della risposta di @ Chris-Montanaro per controllare un URL di terze parti inaffidabile e l'utilizzo whoissul risultato è problematica su diversi livelli. Nota l'URL suggerito in quella risposta è una pagina 404 in questo momento! Anche se avete fatto trovare un servizio di terze parti che ha fatto il lavoro, sarebbe comparativamente molto lenta (rispetto a controllare un file localmente) ed eventualmente incorrere in problemi di rate-limiting o problemi di rete, o, eventualmente, l'istanza EC2 non hanno nemmeno bisogno accesso alla rete esterna.
  7. Il secondo suggerimento nella risposta di @ Chris-Montanaro per controllare http://169.254.169.254/ è un po 'meglio, ma un altro commentatore osserva che altri fornitori di cloud rendono disponibile questo URL di metadati dell'istanza, quindi devi stare attento a evitare false positivi. Inoltre sarà ancora molto più lento di un file locale, ho visto questo controllo particolarmente lento (diversi secondi per tornare) su istanze pesantemente caricate. Inoltre, dovresti ricordare di passare un -mo un --max-timeargomento per arricciarlo per evitare che si blocchi per un tempo molto lungo, specialmente su un'istanza non EC2 in cui questo indirizzo può portare a nessun posto e bloccarsi (come nella risposta di @ algal ).

Inoltre, non vedo che nessuno abbia menzionato il fallback documentato di Amazon nel controllare il (possibile) file /sys/devices/virtual/dmi/id/product_uuid.

Chi sapeva che determinare se si sta eseguendo su EC2 potrebbe essere così complicato ?! OK, ora che abbiamo (la maggior parte) dei problemi con gli approcci elencati elencati, ecco uno snippet bash suggerito per verificare se stai utilizzando EC2. Penso che questo dovrebbe funzionare generalmente su quasi tutte le istanze di Linux, le istanze di Windows sono un esercizio per il lettore.

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

Ovviamente, è possibile espandere questo con ancora più controlli di fallback e includere la paranoia sulla gestione, ad esempio un falso positivo che si /sys/hypervisor/uuidverifica per iniziare con "ec2" per caso e così via. Ma questa è una soluzione abbastanza buona per scopi illustrativi e probabilmente quasi tutti i casi d'uso non patologici.

[†] Ho ricevuto questa spiegazione dal supporto AWS sulla modifica per le istanze c5 / m5:

Le istanze C5 e M5 usano un nuovo stack hypervisor e i driver del kernel associati non creano file in sysfs (che è montato su / sys) come fanno i driver Xen usati dagli altri tipi di istanza / precedenti . Il modo migliore per rilevare se il sistema operativo è in esecuzione su un'istanza EC2 è tenere conto delle diverse possibilità elencate nella documentazione collegata .


4
Sì compagni di viaggio nel 2018 ... questa è la risposta che stavi cercando.
russellpierce,

reading / sys / devices / virtual / dmi / id / product_uuid richiede anche i privilegi di root
Thayne,

@Thayne corretto - è quello che elifdice il commento sopra quel blocco, ed è per questo che il eliftest usa l' -roperatore di test, che controlla se il file esiste e che hai i permessi di lettura per il file.
Josh Kupershmidt,

Una nota aggiuntiva sui metadati 169.254.169.254 : non è sempre pronto all'avvio. Se hai bisogno di quei metadati per uno script di avvio, dovrai continuare a eseguire il polling fino a quando non sarà pronto. L'ho visto impiegare fino a 30 secondi dopo che l'istanza ha iniziato a eseguire gli script di avvio cloud-init.
vacri

15

Cerca i metadati tramite il nome di dominio interno EC2 anziché IP, che restituirà un errore DNS rapido se non sei su EC2 ed evita conflitti IP o problemi di routing:

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

Su alcune distribuzioni, sistemi molto semplici, o molto presto nelle fasi installion riccio non è disponibile. Utilizzando invece wget :

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

4
Sfortunatamente, sembra non riuscire in VPC!
Ashe,

2
Inoltre, non utilizzare il carattere punto esclamativo all'interno di doppi apici - la vostra eco potrebbe esplodere con -bash: !": event not found. Usa invece virgolette singole per quelle echos.
Josh Kupershmidt,

1
questo probabilmente presuppone che il server stia ancora utilizzando server DNS EC2 che conoscono la zona ec2.internal e che nessuno ha modificato /etc/resolv.conf in 8.8.8.8 o implementato la propria infrastruttura DNS.
Lamont

1
AWS sembra aver rotto questo. Non riesco più a risolvere instance-data.ec2.internal. instance-data.us-west-2.compute.internal funziona, comunque, almeno per ora.
Bryan Larsen,

14

Se l'obiettivo è stabilire se si tratta di un'istanza EC2 O di un altro tipo di istanza cloud, come Google, allora dmidecodefunziona molto bene e non è necessaria alcuna rete. Mi piace questo vs alcuni degli altri approcci perché il percorso dell'URL dei metadati è diverso per EC2 e 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

Mi aspetto che funzioni bene in altri ambienti VM e persino su hardware reale - non mi aspetto che nessun fornitore di hardware spedisca sistemi in cui la versione del BIOS dice "amazon" ...
Guss

Sulle mie istanze di Ubuntu EC2 questo ritorna 1.0- nessuna menzione amazon.
Nate,

5

I nomi host possono cambiare, eseguire un whois contro il tuo IP pubblico:

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

o fai clic sull'URL dei metadati AWS

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

2
Aggiungi un --connect-timeout 1 alla seconda istruzione curl per fallire rapidamente se non stai eseguendo su EC2.
Jonathan Oliver,

1
FWIW, l'utilizzo dell'URL dei metadati può indicare che è in esecuzione come istanza cloud, ma non può determinare in modo conclusivo se è specificamente EC2. OpenStack ed Eucalyptus usano anche lo stesso URI dei metadati. So che si tratta di scegliere le lendini, ma per il mio lavoro, quale fornitore di cloud è importante.
EmmEff,

5

Funziona bene anche con host Linux in ec2 e non richiede la rete e tutti i timeout correlati:

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

Funziona, perché Amazon definisce questa voce in questo modo:

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


2018/05/01; sembra non essere valido su istanze M5 che eseguono Ubuntu.
russellpierce,

Sulle mie istanze di Ubuntu EC2 questo ritorna 1.0. Nessuna menzione di amazon.
Nate,

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

ma non so quanto sia portatile attraverso le distribuzioni.


2
Bene, certamente non funzionerà su istanze di Windows EC2.
Ceejayoz,

1
Preferisco questo metodo poiché non comporta un'interazione di rete che può bloccarsi per tutti i tipi di motivi. L'uso di timeout per uno scambio HTTP non è garantito per evitare blocchi. Non mi importa delle istanze di Windows.
Hannes,

Questo è esattamente quello di cui avevo bisogno! Molto meglio che arricciare qualcosa, grazie!
qwertzguy,

1
Prendi in considerazione l'utilizzo dell'UUID completo, nel caso in cui anche l'UUID dell'hypervisor di altri fornitori inizi con "ec2". La possibilità che ciò accada è 1 su 4096, il che non è trascurabile.
Hannes,

1
In realtà, il confronto dell'intero UUID non funziona poiché ho visto più UUID hypervisor diversi in natura. Iniziano tutti con "ec2", quindi questa risposta funziona così com'è.
Hannes,

3

Risposta rapida:

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

Ho usato una delle risposte pubblicate qui per oltre un anno, ma non funziona con i nuovi tipi di istanza 'c5' (sto lavorando per l'aggiornamento da 'c4' ora).

Mi piace questa soluzione perché sembra la meno probabile che si rompa in futuro.

Sui vecchi tipi di istanza e su quelli più recenti, questo file è presente e inizia con "EC2". Ho controllato Ubuntu in esecuzione su VirtualBox (che anch'io devo supportare) e contiene la stringa 'VirtualBox'.

Come notato da un precedente poster (ma è stato facile perdere) - c'è la documentazione di Amazon sui modi per farlo - che include la mia risposta.

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


2

Forse puoi usare "facter":

"Facter è una libreria multipiattaforma per il recupero di semplici fatti del sistema operativo, come il sistema operativo, la distribuzione di Linux o l'indirizzo MAC."

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

Ad esempio, se diamo uno sguardo al fatto 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

Se il ricciolo è installato, questo comando restituirà 0 se si esegue in EC2 e diverso da zero se non si è:

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

Cerca di estrarre i metadati EC2 che dichiarano l'ID AMI. Se ciò non riesce dopo 3 secondi, si presume che non sia in esecuzione in EC2.


0

Un po 'tardi a questa festa, tuttavia mi sono imbattuto in questo post e ho trovato questa documentazione di AWS:

Per un metodo definitivo e crittograficamente verificato per identificare un'istanza EC2, controllare il documento di identità dell'istanza, inclusa la sua firma. Questi documenti sono disponibili su ogni istanza EC2 all'indirizzo locale non instradabile http://169.254.169.254/latest/dynamic/instance-identity/

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

Ciò, ovviamente, richiede l'overhead di rete sebbene sia possibile impostare il timeout di arricciatura in questo modo:

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

Ciò imposta il timeout su 5 secondi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.