Làm thế nào để biết máy có phải là phiên bản EC2 không


43

Tôi muốn chạy một số tập lệnh trên các máy chủ là phiên bản EC2 nhưng tôi không biết làm thế nào để chắc chắn rằng máy chủ đó thực sự là một phiên bản EC2.

Tôi đã thực hiện một số thử nghiệm, nhưng điều này là không đủ:

  • Kiểm tra xem nhị phân ec2_userdata có sẵn không (nhưng điều này sẽ không luôn luôn đúng)
  • Kiểm tra tính khả dụng của " http://169.254.169.254/latest/meta-data " (nhưng điều này sẽ luôn đúng? Và "IP ma thuật" này là gì?)


Đây thực sự là một địa chỉ APIPA, khá lạ khi sử dụng làm tài liệu tham khảo cho một dịch vụ quan trọng như truy xuất dữ liệu meta.
Matthieu Cerda

2
Phạm vi IP của EC2 là công khai (mặc dù thay đổi theo thời gian). Nếu bạn theo kịp danh sách hiện tại, bạn có thể kiểm tra IP phiên bản theo phạm vi đó.
Karma Fusebox

2
Đừng dựa vào 169.254.169.254 nếu bạn muốn EC2 và chỉ các hệ thống tương tự EC2 - EC2 như Eucalyptus cũng hỗ trợ nó. engage.eucalyptus.com/customer/portal/articles/...
ceejayoz

1
Bạn có cần phương pháp để chống lại kẻ tấn công đã root máy chủ và đang cố gắng giả mạo bạn nghĩ rằng đó là một ví dụ EC2 cho mục đích độc hại của mình không? Nếu bạn làm, thì nó sẽ khó hơn nhiều.
Mike Scott

Câu trả lời:


3

Thực tế, có một cách rất đơn giản để phát hiện xem máy chủ có phải là phiên bản EC2 hay không: kiểm tra tra cứu ngược lại IP công cộng của bạn. Các đảo ngược EC2 là khá khó để bỏ lỡ.

Ngoài ra, nếu bạn không sửa đổi nó, tên máy chủ sẽ là đảo ngược của bạn, làm cho nó dễ dàng phát hiện ra nó hơn.

Bạn cũng có thể sử dụng "IP ma thuật" mà bạn đã nói, vì đó thực sự là cách tiêu chuẩn để nhận thẻ EC2 Instance, tuy nhiên, nếu bạn không ở trên mạng EC2, bạn sẽ phải chờ thời gian chờ, thường là không mong muốn ...

Nếu các phương pháp này là không đủ, chỉ cần thực hiện một số lần IP của bạn và kiểm tra xem bạn có ở trong khối IP EC2 của Amazon không.

EDIT: Bạn có thể sử dụng bit shell nhỏ này:

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

Mặc dù cẩn thận, [[là một bashism. Bạn cũng có thể sử dụng Python hoặc Perl uniline, YMMV.


13
điều này không hoạt động trong VPC hoặc môi trường nơi bạn đã thay đổi tên máy chủ; ví dụ. nếu máy của bạn ở trong domain.local
Preflightsiren

2
bit tên máy chủ bị ràng buộc để thất bại.
Dan Pritts

3
hostname -dtrở vềeu-west-1.compute.internal
Bulletmagnet

42

Đã thay đổi câu trả lời của Hannes để tránh thông báo lỗi và bao gồm sử dụng ví dụ trong tập lệnh:

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

Điều này không hoạt động trong các trường hợp Windows. Ưu điểm hơn so với curl là nó gần với tức thời trên cả EC2 và không EC2.


4
AWS dường như cũng khuyên bạn nên làm theo cách này docs.aws.amazon.com/AWSEC2/latest/UserGuide/ Kẻ
Mike

3
Tôi thích phương pháp này. Chỉ cần lưu ý rằng một hệ thống không phải EC2 chạy dưới bộ ảo hóa có thể tạo ra UUID bắt đầu bằng ec2- dương tính giả. Điều đó là không thể (cơ hội 1 trong 256) và chỉ khi bạn đang sử dụng một trình ảo hóa cư trú trong tệp đó. Đó là lý do tại sao tài liệu được liên kết ở trên nói rằng bạn có thể đang xem xét một ví dụ EC2.
Nate

1
@Nate, điểm tốt, nhưng không nên là cơ hội 1 trên 4096? (16 x 16 x 16)
tự đại diện

2
@Wildcard: Tôi không thể chỉnh sửa nhận xét của mình, nhưng điều đó đúng.
Nate

7
NGUY HIỂM! Phương pháp này đã hoạt động đáng tin cậy đối với chúng tôi trong nhiều năm ... cho đến gần đây, với các loại c5 và m5 mới nhất không có tệp này . Vì vậy, tôi phải thêm một kiểm tra dự phòng 169.254.169.254 để xử lý các trường hợp đó.
Josh Kupershmidt

20

Đầu tiên, tôi cảm thấy cần phải đăng một câu trả lời mới vì những vấn đề tế nhị sau đây với các câu trả lời hiện có và sau khi nhận được câu hỏi về nhận xét của tôi về câu trả lời của @ qwertzguy . Dưới đây là các vấn đề với các câu trả lời hiện tại:

  1. Các câu trả lời được chấp nhận từ @MatthieuCerda chắc chắn không làm việc đáng tin cậy, ít nhất là không phải trên bất kỳ trường hợp VPC Tôi đã kiểm tra lại. (Trong trường hợp của tôi, tôi nhận được tên VPC hostname -d, được sử dụng cho DNS nội bộ, không phải bất cứ thứ gì có "amazonaws.com" trong đó.)
  2. Các câu trả lời cao nhất bình chọn từ @qwertzguy không làm việc trên M5 hay c5 trường mới , mà không có tập tin này. Amazon bỏ qua tài liệu này thay đổi hành vi AFAIK, mặc dù trang tài liệu về chủ đề này có ghi "... Nếu / sys / hypanneror / uuid tồn tại ...". Tôi đã hỏi bộ phận hỗ trợ của AWS xem sự thay đổi này có chủ ý hay không, xem bên dưới.
  3. Câu trả lời từ @Jer không nhất thiết phải hoạt động ở mọi nơi vì việc instance-data.ec2.internaltra cứu DNS có thể không hoạt động. Trong một phiên bản Ubuntu EC2 VPC mà tôi vừa thử nghiệm, tôi thấy: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal điều này sẽ khiến mã dựa vào phương pháp này kết luận sai rằng nó không có trên EC2!
  4. Câu trả lời để sử dụngdmidecode từ @tamale có thể hoạt động, nhưng phụ thuộc vào bạn a.) Có dmidecodesẵn trong trường hợp của bạn và b.) Có sudokhả năng root hoặc mật khẩu không có trong mã của bạn.
  5. Câu trả lời để kiểm tra / sys / thiết bị / ảo / dmi / id / bios_version từ @spkane là sai lầm nguy hiểm! Tôi đã kiểm tra một M5 dụ Ubuntu 14.04, và có một bios_versionsố 1.0. Tập tin này hoàn toàn không được ghi nhận trên tài liệu của Amazon , vì vậy tôi thực sự sẽ không dựa vào nó.
  6. Phần đầu tiên của câu trả lời từ @ Chris-Montanaro để kiểm tra URL của bên thứ 3 không đáng tin cậy và việc sử dụng whoiskết quả là có vấn đề ở nhiều cấp độ. Lưu ý rằng URL được đề xuất trong câu trả lời đó là một trang 404 ngay bây giờ! Thậm chí nếu bạn đã tìm thấy một dịch vụ của bên thứ 3 mà đã làm việc, nó sẽ là tương đối rất chậm (so với kiểm tra một tập tin cục bộ) và có thể chạy vào các vấn đề hạn chế tỷ lệ hoặc các vấn đề mạng, hoặc có thể là ví dụ EC2 của bạn thậm chí không có truy cập mạng bên ngoài.
  7. Gợi ý thứ hai trong câu trả lời từ @ Chris-Montanaro để kiểm tra http://169.254.169.254/ tốt hơn một chút, nhưng một nhà bình luận khác lưu ý rằng các nhà cung cấp đám mây khác cung cấp URL siêu dữ liệu phiên bản này, vì vậy bạn phải cẩn thận để tránh sai tích cực. Ngoài ra, nó vẫn sẽ chậm hơn nhiều so với một tệp cục bộ, tôi đã thấy kiểm tra này đặc biệt chậm (vài giây để trở lại) trong các trường hợp được tải nặng. Ngoài ra, bạn nên nhớ chuyển một -mhoặc --max-timeđối số để cuộn tròn để tránh nó bị treo trong một thời gian rất dài, đặc biệt là trong trường hợp không phải EC2 nơi địa chỉ này có thể dẫn đến hư không và treo (như trong câu trả lời của @ algal ).

Ngoài ra, tôi không thấy rằng bất kỳ ai đã đề cập đến dự phòng tài liệu của Amazon về việc kiểm tra tệp (có thể) /sys/devices/virtual/dmi/id/product_uuid.

Ai biết rằng việc xác định xem bạn có đang chạy trên EC2 có thể rất phức tạp không?! OK, bây giờ chúng tôi có (hầu hết) các vấn đề với các cách tiếp cận được liệt kê, đây là một đoạn bash được đề xuất để kiểm tra xem bạn có đang chạy trên EC2 không. Tôi nghĩ rằng điều này sẽ hoạt động chung trên hầu hết các phiên bản Linux, các phiên bản Windows là một bài tập cho người đọc.

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

Rõ ràng, bạn có thể mở rộng điều này với các kiểm tra dự phòng thậm chí nhiều hơn, và bao gồm sự hoang tưởng về việc xử lý, ví dụ như một dương tính giả từ việc /sys/hypervisor/uuidxảy ra để bắt đầu với "ec2" một cách tình cờ, v.v. Nhưng đây là một giải pháp đủ tốt cho mục đích minh họa và có lẽ gần như tất cả các trường hợp sử dụng không bệnh lý.

[†] Nhận lại lời giải thích này từ bộ phận hỗ trợ AWS về thay đổi cho các trường hợp c5 / m5:

Các phiên bản C5 và M5 sử dụng ngăn xếp hypanneror mới và các trình điều khiển hạt nhân liên quan không tạo các tệp trong sysfs (được gắn tại / sys) như các trình điều khiển Xen được sử dụng bởi các loại cá thể cũ / cũ hơn . Cách tốt nhất để phát hiện xem hệ điều hành có chạy trên phiên bản EC2 hay không là tính đến các khả năng khác nhau được liệt kê trong tài liệu bạn liên kết .


4
Có bạn đồng hành năm 2018 ... đây là câu trả lời bạn đang tìm kiếm.
russellpierce

đọc / sys / thiết bị / ảo / dmi / id / sản phẩm_uuid cũng yêu cầu quyền root
Thayne

@Thayne đúng - đó là những gì nhận xét ở trên elifkhối đó nói và đó là lý do tại sao elifkiểm tra sử dụng -rtoán tử kiểm tra, kiểm tra xem tệp có tồn tại hay không và bạn có đọc quyền cho tệp không.
Josh Kupershmidt

Một lưu ý bổ sung về siêu dữ liệu 169.254.169.254 - nó không phải lúc nào cũng sẵn sàng khi khởi động. Nếu bạn cần siêu dữ liệu đó cho một bản khởi động, bạn sẽ cần tiếp tục bỏ phiếu cho đến khi nó sẵn sàng. Tôi đã thấy nó mất tới 30 giây sau khi cá thể bắt đầu chạy các bản khởi động đám mây.
vacri

15

Tìm siêu dữ liệu theo tên miền nội bộ EC2 thay vì IP, sẽ trả về lỗi DNS nhanh nếu bạn không ở trên EC2 và tránh xung đột IP hoặc các sự cố định tuyến:

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

Trên một số distro, các hệ thống rất cơ bản, hoặc rất sớm ở giai đoạn cài đặt curl không có sẵn. Sử dụng wget thay thế:

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

4
Thật không may, dường như thất bại trong VPC!
Ashe

2
Cũng không sử dụng ký tự dấu chấm than bên trong dấu ngoặc kép - tiếng vang của bạn có thể thổi lên với -bash: !": event not found. Sử dụng dấu ngoặc đơn cho những echos thay thế.
Josh Kupershmidt

1
điều này có thể giả định rằng máy chủ vẫn đang sử dụng các máy chủ DNS của EC2 biết về vùng ec2.iternal và không ai thay đổi /etc/resolv.conf thành 8.8.8.8 hoặc cuộn cơ sở hạ tầng DNS của riêng họ.
lamont

1
AWS dường như đã phá vỡ điều này. Tôi không còn có thể giải quyết cá thể-data.ec2.iternal. Tuy nhiên, data-data.us-west-2.compute.iternal hoạt động, ít nhất là cho đến bây giờ.
Bryan Larsen

14

Nếu mục tiêu là để biết liệu đó có phải là một thể hiện EC2 HOẶC một loại thể hiện đám mây khác, như google, thì nó dmidecodehoạt động rất độc đáo và không cần kết nối mạng. Tôi thích điều này so với một số cách tiếp cận khác vì đường dẫn url siêu dữ liệu khác với EC2 và 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

Tôi hy vọng điều này sẽ hoạt động tốt trong các môi trường VM khác và ngay cả trên phần cứng thực sự - Tôi không mong đợi bất kỳ nhà cung cấp phần cứng nào cung cấp các hệ thống trong đó phiên bản bios nói "amazon" ...
Guss

Trên phiên bản Ubuntu EC2 của tôi, điều này trả về 1.0- không đề cập đến amazon.
Nate

5

Tên máy chủ có khả năng thay đổi, chạy whois chống lại IP công khai của bạn:

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

hoặc nhấn url dữ liệu meta 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
Thêm một --connect-timeout 1 vào câu lệnh curl thứ hai để nhanh chóng thất bại nếu bạn không chạy trên EC2.
Jonathan Oliver

1
FWIW, sử dụng URL siêu dữ liệu có thể cho biết nó đang chạy như một phiên bản đám mây, nhưng không thể xác định một cách cụ thể nếu đó là EC2 cụ thể. OpenStack và Eucalyptus cũng sử dụng URI siêu dữ liệu tương tự. Tôi biết điều này là chọn nits, nhưng đối với công việc của tôi, nhà cung cấp đám mây nào quan trọng.
EmmEff

5

Điều này cũng hoạt động tốt cho các máy chủ Linux trong ec2 và không yêu cầu mạng và bất kỳ thời gian chờ liên quan nào:

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

Điều này hoạt động, bởi vì Amazon định nghĩa mục này như vậy:

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


2018-05-01; dường như không hợp lệ trên các phiên bản M5 chạy Ubuntu.
russellpierce

Trên phiên bản Ubuntu EC2 của tôi, điều này trả về 1.0. Không đề cập đến amazon.
Nate

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

nhưng tôi không biết làm thế nào di động này trên các bản phân phối.


2
Chà, nó chắc chắn sẽ không hoạt động trên các phiên bản Windows EC2.
ceejayoz

1
Tôi thích phương pháp này vì nó không liên quan đến tương tác mạng có thể bị treo vì mọi lý do. Việc sử dụng thời gian chờ để trao đổi HTTP không được đảm bảo để tránh bị treo. Tôi không quan tâm đến các phiên bản Windows.
Hannes

Đó chính xác là những gì tôi cần! Cách tốt hơn là cuộn tròn một cái gì đó, cảm ơn!
qwertzguy

1
Cân nhắc sử dụng UUID đầy đủ, chỉ trong trường hợp UUID của nhà cung cấp dịch vụ ảo hóa khác của nhà cung cấp khác cũng bắt đầu bằng "ec2". Cơ hội của điều đó xảy ra là 1 trên 4096, không đáng kể.
Hannes

1
Trên thực tế, so sánh toàn bộ UUID không hoạt động vì tôi đã thấy nhiều UUID hypanneror khác nhau trong tự nhiên. Tất cả đều bắt đầu bằng "ec2", vì vậy câu trả lời này hoạt động như vậy.
Hannes

3

Câu trả lời nhanh:

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

Tôi đã sử dụng một trong những câu trả lời được đăng ở đây trong hơn một năm - nhưng nó không hoạt động trên các loại ví dụ 'c5' mới (hiện tôi đang làm việc để nâng cấp từ 'c4').

Tôi thích giải pháp này vì nó có vẻ như ít có khả năng phá vỡ nhất trong tương lai.

Trên các loại phiên bản cũ hơn và các loại mới hơn, tệp này có mặt và bắt đầu bằng 'EC2'. Tôi đã kiểm tra trên Ubuntu chạy trên VirtualBox (tôi cũng cần hỗ trợ) và nó chứa chuỗi 'VirtualBox'.

Như một poster trước đã ghi chú (nhưng rất dễ bỏ lỡ) - có tài liệu của Amazon về các cách để làm điều này - bao gồm câu trả lời của tôi.

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


2

Có lẽ bạn có thể sử dụng "facter":

"Facter là một thư viện đa nền tảng để truy xuất các sự kiện hệ điều hành đơn giản, như hệ điều hành, phân phối linux hoặc địa chỉ MAC."

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

Ví dụ: nếu chúng ta xem thực tế 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

Nếu bạn đã cài đặt curl, lệnh này sẽ trả về 0 nếu bạn đang chạy trong EC2 và khác không nếu bạn không:

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

Nó cố gắng kéo siêu dữ liệu EC2 khai báo AMI-ID. Nếu điều này không thành công sau 3 giây, nó giả sử nó không chạy trong EC2.


0

Một chút muộn cho bữa tiệc này, tuy nhiên tôi đã xem qua bài đăng này và sau đó tìm thấy tài liệu AWS này:

Để biết phương pháp xác định chính xác và xác minh bằng mật mã để xác định một thể hiện EC2, hãy kiểm tra tài liệu nhận dạng cá thể, bao gồm cả chữ ký của nó. Các tài liệu này có sẵn trên mọi phiên bản EC2 tại địa chỉ địa phương, không thể định tuyến http://169.254.169.254/latest/dynamic/instance-identity/

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

Tất nhiên, điều này đòi hỏi chi phí mạng mặc dù bạn có thể đặt thời gian chờ cong như vậy:

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

Điều đó đặt thời gian chờ là 5s.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.