Cara mengetahui apakah mesin adalah turunan EC2

43

Saya ingin menjalankan beberapa skrip pada host yang merupakan instance EC2 tapi saya tidak tahu bagaimana memastikan bahwa host tersebut benar - benar instance EC2.

Saya telah melakukan beberapa tes, tetapi ini tidak cukup:

  • Uji apakah biner ec2_userdata tersedia (tetapi ini tidak selalu benar)
  • Uji ketersediaan " http://169.254.169.254/latest/meta-data " (tetapi apakah ini akan selalu benar? Dan apa ini "IP ajaib"?)
Kelindil
sumber
Ini sebenarnya alamat APIPA, yang cukup aneh untuk digunakan sebagai referensi untuk layanan penting seperti pengambilan data meta.
Matthieu Cerda
2
Rentang IP EC2s bersifat publik (meskipun bervariasi dari waktu ke waktu). Jika Anda mengikuti daftar saat ini Anda dapat memeriksa IP instance terhadap rentang itu.
Karma Fusebox
2
Jangan mengandalkan 169.254.169.254 jika Anda menginginkan EC2 dan hanya EC2 - sistem serupa EC2 seperti Eucalyptus juga mendukungnya. engagement.eucalyptus.com/customer/portal/articles/…
ceejayoz
1
Apakah Anda memerlukan metode untuk bekerja melawan penyerang yang memiliki root pada host, dan mencoba untuk menipu Anda untuk berpikir bahwa itu adalah contoh EC2 untuk tujuan jahatnya sendiri? Jika Anda melakukannya, maka itu akan jauh lebih sulit.
Mike Scott

Jawaban:

3

Yah sebenarnya, ada cara yang sangat sederhana untuk mendeteksi apakah host adalah instance EC2: periksa reverse lookup IP publik Anda. Pembalikan EC2 cukup sulit untuk dilewatkan.

Juga, jika Anda tidak memodifikasinya, nama host harus Anda balikkan, membuatnya semakin mudah dikenali.

Anda mungkin juga menggunakan "IP ajaib" yang Anda bicarakan, karena memang cara standar untuk mendapatkan tag EC2 Instance, namun, jika Anda tidak berada di jaringan EC2, Anda harus menunggu waktu tunggu, yang umumnya tidak diinginkan ...

Jika metode ini tidak cukup, cukup lakukan whois IP Anda dan periksa apakah Anda ada di dalam dan blok Amazon EC2.

EDIT: Anda dapat menggunakan bit shell kecil ini:

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

Hati-hati, [[adalah bashism. Anda juga dapat menggunakan Python atau Perl uniline, YMMV.

Matthieu Cerda
sumber
13
ini tidak berfungsi di VPC atau lingkungan di mana Anda telah mengubah nama host; misalnya. jika mesin Anda ada di domain.local
Preflightsiren
2
bit hostname pasti gagal.
Dan Pritts
3
hostname -dkembalieu-west-1.compute.internal
Bulletmagnet
42

Mengubah jawaban Hannes untuk menghindari pesan kesalahan dan menyertakan contoh penggunaan dalam skrip:

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

Ini tidak berfungsi dalam instance Windows. Keuntungan lebih dari curl adalah karena hampir instan pada EC2 dan non-EC2.

qwertzguy
sumber
4
AWS juga menyarankan untuk melakukannya dengan cara ini docs.aws.amazon.com/AWSEC2/latest/UserGuide/…
Mike
3
Saya suka metode ini. Perlu diketahui bahwa sistem non-EC2 yang berjalan di bawah hypervisor dapat menghasilkan UUID yang dimulai dengan ec2- false positive. Ini tidak mungkin (kemungkinan 1-in-256) dan hanya jika Anda menggunakan hypervisor yang mengisi file itu. Itu sebabnya dokumentasi yang ditautkan di atas mengatakan "Anda mungkin melihat contoh EC2".
Nate
1
@Nate, poin bagus, tapi bukankah itu peluang 1 banding 4096? (16 x 16 x 16)
Wildcard
2
@ Kartu Memori: Saya tidak dapat mengedit komentar saya, tetapi itu benar.
Nate
7
BAHAYA! Metode ini telah bekerja dengan andal bagi kami selama bertahun-tahun ... sampai baru-baru ini, dengan tipe c5 dan m5 terbaru yang tidak memiliki file ini . Jadi saya harus menambahkan cek fallback 169.254.169.254 untuk menangani hal-hal tersebut.
Josh Kupershmidt
20

Pertama, saya merasa perlu memposting jawaban baru karena masalah halus berikut dengan jawaban yang ada, dan setelah menerima pertanyaan tentang komentar saya pada jawaban @ qwertzguy . Inilah masalah dengan jawaban saat ini:

  1. The jawaban yang diterima dari @MatthieuCerda pasti tidak bekerja andal, setidaknya tidak pada setiap kasus VPC saya diperiksa terhadap. (Dalam contoh saya, saya mendapatkan nama VPC untuk hostname -d, yang digunakan untuk DNS internal, bukan apa pun dengan "amazonaws.com" di dalamnya.)
  2. Jawaban dengan pilihan tertinggi dari @qwertzguy tidak berfungsi pada instance m5 atau c5 baru , yang tidak memiliki file ini. Amazon lalai mendokumentasikan perubahan perilaku ini AFAIK, meskipun halaman dokumen tentang hal ini mengatakan "... Jika / sys / hypervisor / uuid ada ...". Saya bertanya dukungan AWS apakah perubahan ini disengaja, lihat di bawah †.
  3. The jawaban dari @Jer tidak selalu bekerja di mana-mana karena instance-data.ec2.internalDNS lookup mungkin tidak bekerja. Pada contoh Ubuntu EC2 VPC yang baru saja saya uji, saya melihat: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal yang akan menyebabkan kode mengandalkan metode ini untuk menyimpulkan itu bukan pada EC2!
  4. The Jawaban untuk menggunakandmidecode dari @tamale dapat bekerja, tetapi bergantung pada Anda.) Memiliki dmidecodetersedia pada contoh Anda, dan b.) Memiliki akar atau sudokemampuan sandi-kurang dari dalam kode Anda.
  5. The jawaban untuk memeriksa / sys / perangkat / virtual / DMI / id / bios_version dari @spkane yang berbahaya menyesatkan! Aku memeriksa satu Ubuntu 14.04 m5 misalnya, dan mendapat bios_versiondari 1.0. File ini tidak didokumentasikan sama sekali di dokumen Amazon , jadi saya benar-benar tidak akan bergantung padanya.
  6. Bagian pertama dari jawaban dari @ Chris-Montanaro untuk memeriksa URL pihak ketiga yang tidak dapat diandalkan dan digunakan whoispada hasilnya bermasalah pada beberapa level. Perhatikan URL yang disarankan dalam jawaban itu adalah halaman 404 sekarang! Bahkan jika Anda menemukan layanan pihak ke-3 yang bekerja, itu akan relatif sangat lambat (dibandingkan dengan memeriksa file secara lokal) dan mungkin mengalami masalah pembatasan tingkat atau masalah jaringan, atau mungkin instance EC2 Anda bahkan tidak memiliki akses jaringan luar.
  7. Saran kedua dalam jawaban dari @ Chris-Montanaro untuk memeriksa http://169.254.169.254/ sedikit lebih baik, tetapi komentator lain mencatat bahwa penyedia cloud lain membuat URL metadata instance ini tersedia, jadi Anda harus berhati-hati untuk menghindari false positif. Juga masih akan jauh lebih lambat daripada file lokal, saya telah melihat pemeriksaan ini sangat lambat (beberapa detik untuk kembali) pada contoh yang banyak dimuat. Juga, Anda harus ingat untuk meloloskan argumen -matau --max-timemenggulung agar tidak menggantung untuk waktu yang sangat lama, terutama pada contoh non-EC2 di mana alamat ini dapat mengarah ke mana-mana dan menggantung (seperti dalam jawaban @ algal ).

Juga, saya tidak melihat bahwa ada orang yang menyebutkan mundurnya Amazon yang didokumentasikan untuk memeriksa file (mungkin) /sys/devices/virtual/dmi/id/product_uuid.

Siapa yang tahu bahwa menentukan apakah Anda menggunakan EC2 bisa sangat rumit ?! Oke, sekarang kami memiliki (sebagian besar) masalah dengan pendekatan terdaftar yang tercantum, berikut ini cuplikan bash yang disarankan untuk memeriksa apakah Anda menjalankan EC2. Saya pikir ini harus bekerja secara umum pada hampir semua contoh Linux, contoh Windows adalah latihan untuk pembaca.

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

Jelas, Anda dapat memperluas ini dengan lebih banyak lagi fallback cheque, dan menyertakan paranoia tentang penanganan, mis. Salah positif /sys/hypervisor/uuidterjadi mulai dengan "ec2" secara kebetulan dan sebagainya. Tetapi ini adalah solusi yang cukup baik untuk tujuan ilustrasi dan mungkin hampir semua kasus penggunaan non-patologis.

[†] Dapatkan kembali penjelasan dari dukungan AWS ini tentang perubahan untuk instance c5 / m5:

Mesin virtual C5 dan M5 menggunakan tumpukan hypervisor baru dan driver kernel yang terkait tidak membuat file di sysfs (yang dipasang di / sys) seperti yang dilakukan oleh driver Xen yang digunakan oleh tipe instance lain / lama . Cara terbaik untuk mendeteksi apakah sistem operasi berjalan pada instance EC2 adalah dengan memperhitungkan berbagai kemungkinan yang tercantum dalam dokumentasi yang Anda tautkan .

Josh Kupershmidt
sumber
4
Ya sesama pelancong di tahun 2018 ... ini adalah jawaban yang Anda cari.
russellpierce
membaca / sys / devices / virtual / dmi / id / product_uuid juga membutuhkan hak akses root
Thayne
@Thayne benar - itulah yang dikatakan komentar di atas elifblok itu, dan itulah sebabnya eliftes menggunakan -roperator tes, yang memeriksa apakah file tersebut ada dan bahwa Anda telah membaca izin untuk file tersebut.
Josh Kupershmidt
Catatan tambahan pada metadata 169.254.169.254 - tidak selalu siap saat boot. Jika Anda membutuhkan metadata untuk skrip boot, Anda harus terus melakukan polling hingga siap. Saya telah melihatnya membutuhkan waktu hingga 30 detik setelah instance sudah mulai menjalankan skrip boots-init-nya.
vacri
15

Cari metadata dengan nama domain internal EC2 alih-alih IP, yang akan mengembalikan kegagalan DNS cepat jika Anda tidak menggunakan EC2, dan menghindari konflik IP atau masalah perutean:

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

Pada beberapa distro, sistem yang sangat mendasar, atau sangat awal pada tahap pemasangan, curl tidak tersedia. Menggunakan wget gantinya:

wget -q http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"
Yer
sumber
4
Sayangnya, tampaknya gagal di VPC!
Ashe
2
Juga tidak menggunakan karakter tanda seru di dalam tanda kutip ganda - gema Anda bisa meledak dengan -bash: !": event not found. Gunakan kutipan tunggal untuk echoitu sebagai gantinya.
Josh Kupershmidt
1
ini mungkin mengasumsikan bahwa server masih menggunakan EC2s DNS server yang tahu tentang zona ec2.internal dan bahwa tidak ada yang mengubah /etc/resolv.conf ke 8.8.8.8 atau menggulung infrastruktur DNS mereka sendiri.
lamont
1
AWS tampaknya telah merusak ini. Saya tidak bisa lagi menyelesaikan instance-data.ec2.internal. instance-data.us-west-2.compute.internal bekerja, setidaknya untuk saat ini.
Bryan Larsen
14

Jika tujuannya adalah untuk mengetahui apakah ini adalah contoh EC2 ATAU jenis cloud contoh lain, seperti google, maka dmidecodeberfungsi dengan sangat baik dan tidak diperlukan jaringan. Saya suka ini vs beberapa pendekatan lain karena jalur url metadata berbeda untuk EC2 dan 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
tamale
sumber
Saya berharap ini berfungsi dengan baik di lingkungan VM lain dan bahkan pada perangkat keras nyata - Saya tidak berharap ada vendor perangkat keras untuk mengirim sistem di mana versi bios mengatakan "amazon" ...
Guss
Pada contoh Ubuntu EC2 saya ini mengembalikan 1.0- tidak disebutkan amazon.
Nate
5

Nama host cenderung berubah, jalankan whois terhadap IP publik Anda:

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

atau tekan url meta-data AWS

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
sumber
2
Tambahkan --connect-timeout 1 ke pernyataan curl kedua agar gagal dengan cepat jika Anda tidak menggunakan EC2.
Jonathan Oliver
1
FWIW, menggunakan URL metadata dapat menunjukkan itu berjalan sebagai contoh cloud, tetapi tidak dapat secara meyakinkan menentukan apakah itu khusus EC2. OpenStack dan Eucalyptus juga menggunakan metadata URI yang sama. Saya tahu ini mengambil nits, tetapi untuk pekerjaan saya, yang penting penyedia cloud.
EmmEff
5

Ini juga berfungsi dengan baik untuk host Linux di ec2 dan tidak memerlukan jaringan dan batas waktu terkait:

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

Ini berfungsi, karena Amazon mendefinisikan entri ini seperti:

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

spkane
sumber
2018-05-01; tampaknya tidak valid pada instance M5 yang menjalankan Ubuntu.
russellpierce
Pada contoh Ubuntu EC2 saya ini kembali 1.0. Tidak disebutkan amazon.
Nate
3
test -f /sys/hypervisor/uuid -a `head -c 3 /sys/hypervisor/uuid` == ec2 && echo yes

tapi saya tidak tahu seberapa portabel ini di seluruh distribusi.

Hannes
sumber
2
Yah, itu pasti tidak akan berfungsi pada contoh Windows EC2.
ceejayoz
1
Saya lebih suka metode ini karena tidak melibatkan interaksi jaringan yang dapat digantung untuk semua jenis alasan. Menggunakan batas waktu untuk pertukaran HTTP tidak dijamin untuk mencegah hang. Saya tidak peduli dengan instance Windows.
Hannes
Itulah tepatnya yang saya butuhkan! Jauh lebih baik daripada meringkuk sesuatu, terima kasih!
qwertzguy
1
Pertimbangkan untuk menggunakan UUID lengkap, untuk berjaga-jaga seandainya beberapa vendor lain hypervisor UUID juga dimulai dengan "ec2". Peluang yang terjadi adalah 1 banding 4096 yang tidak dapat diabaikan.
Hannes
1
Sebenarnya, membandingkan seluruh UUID tidak berfungsi karena saya telah melihat beberapa UUID hypervisor berbeda di alam liar. Mereka semua mulai dengan "EC2", jadi jawaban ini berfungsi apa adanya.
Hannes
3

Jawaban cepat:

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

Saya telah menggunakan salah satu jawaban yang diposting di sini selama lebih dari setahun - tetapi itu tidak berfungsi pada tipe instance 'c5' yang baru (saya sedang mengerjakan peningkatan dari 'c4' sekarang).

Saya suka solusi ini karena sepertinya paling tidak mungkin pecah di masa depan.

Pada jenis instance yang lebih lama, dan yang lebih baru, file ini ada dan dimulai dengan 'EC2'. Saya memeriksa Ubuntu yang berjalan di VirtualBox (yang saya juga perlu mendukung) dan berisi string 'VirtualBox'.

Seperti yang dicatat oleh poster sebelumnya (tapi mudah untuk dilewatkan) - ada dokumentasi Amazon tentang cara untuk melakukan ini - yang termasuk jawaban saya.

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

Zach Anthony
sumber
2

Mungkin Anda bisa menggunakan "facter":

"Facter adalah pustaka lintas platform untuk mengambil fakta sistem operasi sederhana, seperti sistem operasi, distribusi linux, atau alamat MAC."

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

Sebagai contoh, jika kita melihat fakta 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
jmprusi
sumber
1

Jika Anda memiliki curl diinstal, perintah ini akan mengembalikan 0 jika Anda menjalankan dalam EC2 dan non-nol jika Anda tidak:

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

Mencoba menarik metadata EC2 menyatakan AMI-ID. Jika ini tidak berhasil setelah 3 detik, ia menganggap itu tidak berjalan di EC2.

ganggang
sumber
0

Agak terlambat ke pesta ini, namun saya menemukan posting ini dan kemudian menemukan dokumentasi AWS ini:

Untuk metode definitif dan diverifikasi secara kriptografis untuk mengidentifikasi instance EC2, periksa dokumen identitas instance, termasuk tanda tangannya. Dokumen-dokumen ini tersedia pada setiap instance EC2 di alamat lokal, non-routable, http://169.254.169.254/latest/dynamic/instance-identity/

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

Ini, tentu saja, membutuhkan overhead jaringan meskipun Anda dapat mengatur batas waktu keriting seperti:

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

Itu menetapkan batas waktu menjadi 5s.

Anak sungai
sumber