Як дізнатися, чи машина є екземпляром EC2


43

Я хотів би запустити кілька сценаріїв на хостах, які є екземплярами EC2, але я не знаю, як бути впевненим, що хост справді є екземпляром EC2.

Я зробив кілька тестів, але цього недостатньо:

  • Перевірте наявність бінарних ec2_userdata (але це не завжди буде правдою)
  • Перевірка наявності " http://169.254.169.254/latest/meta-data " (але чи завжди це буде правдою? І що це за "магічний IP"?)


Це насправді адреса APIPA, що досить дивно використовувати в якості посилання на критичну службу, як пошук метаданих.
Матьє Серда

2
Діапазони IP-адрес EC2 є загальнодоступними (хоча час від часу змінюються). Якщо ви будете в курсі поточного списку, ви можете перевірити IP екземплярів проти цих діапазонів.
Karma Fusebox

2
Не покладайтеся на 169.254.169.254, якщо ви хочете підтримувати EC2 і лише системи EC2 - EC2, такі як Евкаліпт. enable.eucalyptus.com/customer/portal/articles/…
ceejayoz

1
Чи потрібен вам метод для боротьби з нападником, котрий має корінь на хості, і намагається обдурити вас на думку про те, що це екземпляр EC2 для його власних шкідливих цілей? Якщо ви це зробите, то це буде набагато важче.
Майк Скотт

Відповіді:


3

Насправді, існує дуже простий спосіб визначити, що хост - екземпляр EC2: перевірити зворотний пошук вашого загальнодоступного IP-адреси. Реверси EC2 досить важко пропустити.

Крім того, якщо ви не змінили його, ім'я хоста повинно бути вашим зворотним боком, що спростить його виявлення.

Ви також можете використовувати "чарівний IP", про який ви говорили, оскільки це дійсно стандартний спосіб отримати теги інстанції EC2, однак, якщо ви не в мережі EC2, вам доведеться почекати тайм-ауту, який, як правило, не бажано ...

Якщо цих методів недостатньо, просто зробіть сукупність ваших IP-адрес і перевірте, чи перебуваєте ви в блоці та IP-адресі Amazon EC2.

EDIT: Ви можете використовувати цей невеликий біт оболонки:

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

Але обережно, [[це башизм. Ви також можете використовувати Uniline Python або Perl, YMMV.


13
це не працює в VPC або середовищі, де ви змінили ім'я хоста; напр. якщо ваші машини в DOMAIN.LOCAL
Preflightsiren

2
біт імені хоста просто не вдається.
Dan Pritts

3
hostname -dповерненняeu-west-1.compute.internal
Bulletmagnet

42

Змінив відповідь Ханнеса, щоб уникнути повідомлень про помилки та включити приклад використання в сценарій:

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- хибний позитив. Це малоймовірно (шанс 1 на 256) і лише якщо ви використовуєте гіпервізор, який заповнює цей файл. Ось чому в зв'язаній вище документації йдеться про те, що "ви, мабуть, переглядаєте екземпляр EC2".
Нейт

1
@Nate, хороший пункт, але чи не повинен це бути шанс 1 на 4096? (16 x 16 x 16)
Wildcard

2
@Wildcard: Я не можу редагувати свій коментар, але це правильно.
Нейт

7
НЕБЕЗПЕЧНО! Цей метод надійно працював у нас роками ... до недавнього часу, з останніми типами c5 та m5, у яких немає цього файлу . Тому я повинен додати резервний чек 169.254.169.254, щоб обробляти ці екземпляри.
Джош Купершмідт

20

По-перше, я відчув необхідність розмістити нову відповідь через наступні тонкі проблеми з існуючими відповідями, і після отримання запитання про мій коментар до відповіді @ qwertzguy . Ось проблеми з поточними відповідями:

  1. Загальноприйнятий відповідь від @MatthieuCerda безумовно не працює надійно, принаймні не на будь - яких VPC випадках я звіряюся. (У моїх випадках я отримую ім'я VPC hostname -d, яке використовується для внутрішнього DNS, не що-небудь із "amazonaws.com" в ньому.)
  2. Відповідь з найбільш високим голосом від @qwertzguy не працює на нових екземплярах m5 чи c5 , у яких цього файлу немає. Amazon нехтує документацією, щоб така поведінка змінила AFAIK, хоча на сторінці документа з цього приводу написано "... Якщо існує / sys / hypervisor / uuid ...". Я запитав підтримку AWS, чи була ця зміна навмисною, див. Нижче †.
  3. Відповідь від @Jer не обов'язково буде працювати скрізь , тому що instance-data.ec2.internalDNS пошук не може працювати. На екземплярі VPC Ubuntu EC2, який я щойно перевіряв, я бачу: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal що призведе до того, що код, покладаючись на цей метод, помилково зробить висновок, що він не на EC2!
  4. Відповідь використовуватиdmidecode від @tamale може працювати, але покладається на вас.) , Хто має dmidecodeдоступні на вашому екземплярі і б.) , Що мають корінь або sudoбезпарольний здатність з вашого коду.
  5. Відповідь для перевірки / системи / пристрої / віртуальний / DMI / ID / bios_version з @spkane загрозливо в оману! Я перевірив один Ubuntu 14.04 екземпляр m5, і отримав bios_versionз 1.0. Цей файл взагалі не задокументований на документі Amazon , тому я б дуже не покладався на нього.
  6. Перша частина відповіді від @ Chris-Montanaro на перевірку ненадійної сторонньої URL-адреси та використання whoisрезультату є проблематичною на кількох рівнях. Зверніть увагу, що URL-адреса, запропонована у цій відповіді, зараз - сторінка 404! Навіть якщо ви знайшли сторонню службу, яка працювала, вона була б порівняно дуже повільною (порівняно з перевіркою файлу локально) і, можливо, зіткнулася з обмеженнями швидкості або мережевими проблемами, або, можливо, ваш екземпляр EC2 навіть не має зовнішній доступ до мережі.
  7. Друга пропозиція у відповіді від @ Chris-Montanaro перевірити http://169.254.169.254/ трохи краще, але інший коментатор зазначає, що інші постачальники хмари роблять доступною URL-адресу метаданих цього примірника, тому вам слід бути обережними, щоб уникнути помилкових позитивні. Крім того, він все ще буде набагато повільніше, ніж локальний файл, я бачив, що ця перевірка є особливо повільною (кілька секунд, щоб повернутися) на сильно завантажених екземплярах. Крім того, вам слід пам’ятати про те, щоб передати аргумент -mабо --max-timeаргумент для згортання, щоб уникнути його зависання дуже довго, особливо на екземплярі, який не стосується EC2, коли ця адреса може призвести нікуди і зависати (як у відповіді @ algal ).

Крім того, я не бачу, щоб хтось згадав про задокументовану відмову Amazon щодо перевірки (можливого) файлу /sys/devices/virtual/dmi/id/product_uuid.

Хто знав, що визначити, чи ти працюєш на EC2, може бути таким складним ?! Гаразд, тепер, коли у нас є (більшість) проблем із переліченими підходами, ось запропонований фрагмент bash, щоб перевірити, чи працюєте ви на EC2. Я думаю, що це має працювати в основному майже на будь-яких екземплярах 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" випадково тощо. Але це досить хороше рішення для ілюстративних цілей і, мабуть, майже всіх непатологічних випадків використання.

[†] Повернення цього пояснення з підтримки AWS щодо зміни для екземплярів c5 / m5:

Екземпляри C5 і M5 використовують новий стек гіпервізорів, і пов'язані з ним драйвери ядра не створюють файли в sysfs (який встановлений на / sys), як це роблять драйвери Xen, використовувані іншими / старішими типами екземплярів . Найкращий спосіб виявити, чи працює операційна система на екземплярі EC2, - це врахувати різні можливості, перелічені в документації, яку ви зв'язали .


4
Так, мандрівник у 2018 році ... це відповідь, яку ви шукали.
russellpierce

read / sys / devices / virtual / dmi / id / product_uuid також вимагає привілеїв root
Thayne

@Thayne правильний - ось що elifговорить коментар вище цього блоку, і саме тому elifтест використовує -rтестовий оператор, який перевіряє, чи існує файл і чи читали ви дозволи для цього файлу.
Джош Купершмідт

Додаткова примітка щодо метаданих 169.254.169.254 - вона не завжди готова під час завантаження. Якщо вам потрібні метадані для початкового сценарію, вам потрібно буде продовжувати опитування, поки воно не буде готове. Я бачив, як це зайняло до 30 секунд після того, як екземпляр почав виконувати свої хмарні скриньки для завантаження.
vacri

15

Шукайте метадані за внутрішнім доменним іменем EC2 замість IP, що поверне швидкий збій DNS, якщо ви не користуєтесь EC2, і уникне конфліктів IP або проблем маршрутизації:

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

У деяких дистрибутивах дуже базові системи або дуже рано на етапі встановлення керма недоступні. Використання wget замість:

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

4
На жаль, здається, що в VPC не виходить!
Еш

2
Також не використовуйте символ знаку оклику в подвійних лапках - ваше відлуння може вибухнути з -bash: !": event not found. Використовуйте echoзамість них одинарні лапки .
Джош Купершмідт

1
це, ймовірно, передбачає, що сервер все ще використовує DNS-сервери EC2, які знають про зону ec2.internal і що ніхто не змінив /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 і навіть на реальному технічному забезпеченні. Я не сподіваюся, що будь-які постачальники апаратних засобів постачають системи, де у версії біосу говориться "amazon" ...
Guss

У моїх випадках Ubuntu EC2 це повернення 1.0- про це не згадується amazon.
Нейт

5

Імена хостів, ймовірно, зміняться, запустіть whois проти вашого загальнодоступного IP-адреси:

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

або натисніть URL-адресу метаданих 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
Додайте --connect-timeout 1 до другого оператора curl, щоб швидко вийти з ладу, якщо ви не працюєте на EC2.
Джонатан Олівер

1
FWIW, використовуючи URL-адресу метаданих, може вказувати, що вона працює як хмарний екземпляр, але не може остаточно визначити, чи це конкретно EC2. OpenStack та евкаліпт також використовують однакові URI метаданих. Я знаю, що це збирання гнид, але для моєї роботи важливий хмарний провайдер.
EmmEff

5

Це також добре працює для хостів Linux у ec2 і не потребує мережі та будь-яких пов’язаних із цим часу:

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; виявляється недійсним для екземплярів M5 під управлінням Ubuntu.
russellpierce

У моїх випадках 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, на випадок, якщо інший гіпервізор UUID постачальника також починається з "ec2". Шанс того, що трапиться, становить 1 на 4096, що не є незначним.
Ханнес

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

Я використовував один з відповідей, розміщених тут більше року, але він не працює на нових типах екземплярів c5 (я зараз працюю над оновленням до 'c4').

Мені подобається це рішення, тому що воно здається, що найменш вірогідне порушення в майбутньому.

На старих типах екземплярів і на нових версіях цей файл присутній і починається з "EC2". Я перевірив Ubuntu, що працює на VirtualBox (що мені також потрібно підтримувати), і він містить рядок "VirtualBox".

Як зазначалося в попередньому плакаті (але це було легко пропустити) - є документація Amazon про способи цього зробити, - яка включає мою відповідь.

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instance.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, ця команда поверне 0, якщо ви працюєте в межах EC2 і не-нульовий, якщо ви не:

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

Він намагається витягнути метадані EC2, декларуючи AMI-ID. Якщо це не вдасться через 3 секунди, воно передбачає, що воно не працює в EC2.


0

Трохи запізнюючись на цю вечірку, проте я натрапив на цю посаду і потім знайшов цю документацію AWS:

Для остаточного та криптографічно підтвердженого способу ідентифікації екземпляра EC2 перевірте документ, що посвідчує особу, включаючи його підпис. Ці документи доступні в кожному екземплярі EC2 за місцевою адресою, що не пересилається, http://169.254.169.254/latest/dynamic/instance-identity/

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

Звичайно, для цього потрібні мережеві накладні витрати, хоча ви можете встановити час очікування вигину так:

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

Це встановлює час очікування на 5s.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.