🐟

そのIPアドレスはAWS所有のIP(v4)アドレスですか?

2022/12/26に公開

皆さんはパブリックIPアドレスを見たときに「このアドレス・・・AWS所有っぽい」と感じる事はありませんか?
私はIPv4アドレスであればなんとなくAWS所有っぽい・・・と感じる時がたまにあります(IPv6は無理です...)
今回はAWSが所有するパブリックIPv4アドレスについて調べていきたいと思います。

対象読者

  • AWSはパブリックIPv4アドレスを何個保有しているのか知りたい方
    忙しい方向け --> 7,000万個ほど保有(2022/12/26時点)
  • お手元のパブリックIPv4アドレスがAWS所有のものか確認したい方

前提

  • 今回はIPv4に限ったお話となります。
    IPv6も同じようなプログラムで計測できると思いますが、アドレス空間が広すぎるのでプログラム実行がどのくらいで終わるか不明です。
  • 記事中のプログラムは計算量などをミリミリと考慮していません。
    こうしたら早くなるなどあればコメントいただけると嬉しいです!
  • 2022/12/26に実行した結果となります。
  • AWSから公表されているIPv4アドレスを対象として集計しました。
    もしかしたらAWSが公表していないIPv4アドレスを保有しているかもしれません。

実行環境

  • OS
    macOS Monterey version 12.6
  • CPU
    Apple M1(Macbook Pro 2020)
  • MEM
    16GB
  • Program
    Python 3.10.9

導入

まずはAWSにて保有しているIPv4の数を調べてみましょう。
AWSではAWS IP アドレスの範囲に記載の通り、jsonファイル(ip-ranges.json)でIPアドレスの範囲を公開しています。

IPv4の総数を集計するPython

「公開されているjsonを元にIPv4の総数を集計する」Pythonです。
get-total-ipv4-count.pyなどの適当な名前をつけて実行してみます。

  • 重複排除の為にset()を利用しています
from ipaddress import ip_network
import requests
IP_RANGE_JSON_URL = "https://ip-ranges.amazonaws.com/ip-ranges.json"


def main():
    ip_range_json = requests.get(IP_RANGE_JSON_URL).json()
    tmp_list = []
    aws_ipv4_list = tmp_list
    for ip_cidr in ip_range_json['prefixes']:
        for ipv4_addr in ip_network(ip_cidr['ip_prefix']):
            aws_ipv4_list.append(str(ipv4_addr))
    print(len(set(aws_ipv4_list)))
    return


if __name__ == "__main__":
    main()

実行例 & 結果

※実行時間計測の為に先頭にtimeと付けていますが、timeは省略可

$ time python3 get-total-ipv4-count.py
71207865
python3 get-total-ipv4-count.py  114.70s user 9.79s system 96% cpu 2:09.02 total

上記の結果より、AWS所有のパブリックIPv4アドレスは71,207,865個(2022/12/26時点)ということがわかりました。
IPv4アドレスの総数が43億個程度なので、1.6%強のIPv4アドレスをAWSが所有しているということになります(すごいですね・・)

IPv4アドレスがAWS所有のものか確認する方法

次に「お手元のIPv4アドレスがAWS所有のものか確認」するPythonです。
aws-owned-ip-address-checker.pyなどの適当な名前をつけて実行してみます。
※第一引数に確認したいIPv4アドレスを指定してください。

  • 第一引数のIPv4がjson内に見つかった時点で早期returnするようになっています。
from ipaddress import ip_network, ip_address
import requests
import sys

IP_RANGE_JSON_URL = "https://ip-ranges.amazonaws.com/ip-ranges.json"


def main(arg_ip):
    ip_range_json = requests.get(IP_RANGE_JSON_URL).json()
    for ip_cidr in ip_range_json['prefixes']:
        tmp_list = []
        aws_ipv4_list = tmp_list
        for ipv4_addr in ip_network(ip_cidr['ip_prefix']):
            aws_ipv4_list.append(str(ipv4_addr))
        # Early return if IPv4 found
        if arg_ip in aws_ipv4_list:
            print(f"{arg_ip} is owned by AWS")
            return
    print(f"{arg_ip} is not owned by AWS")
    return


if __name__ == "__main__":
    try:
        arg_ip = sys.argv[1]
        if (ip_address(arg_ip)).version == 4:
            main(arg_ip)
        else:
            raise ValueError("The first argument is not IPv4 address")
    except:
        print('The first argument must be an IPv4 address')
        print('Usage: python3 aws-owned-ip-address-checker.py 203.0.113.0')

実行例 & 結果

※実行時間計測の為に先頭にtimeと付けていますが、timeは省略可

実行結果①

AWS所有のIPv4アドレスを第一引数として与えた場合

$ time python3 aws-owned-ip-address-checker.py 3.2.34.0
3.2.34.0 is owned by AWS
python3 aws-owned-ip-address-checker.py 3.2.34.0  0.10s user 0.02s system 39% cpu 0.306 total

実行結果②

AWS所有ではないIPv4アドレスを第一引数として与えた場合

$ time python3 aws-owned-ip-address-checker.py 203.0.113.0
203.0.113.0 is not owned by AWS
python3 aws-owned-ip-address-checker.py 203.0.113.0  100.20s user 1.46s system 98% cpu 1:43.35 total

※実行結果②のように、全件検索した場合でも、私の実行環境では100秒程度で確認ができました。

補足ですが、ドキュメントなどで例示するためのIPv4アドレスとしてRFC5737で以下のアドレスが確保されています。
ドキュメントの例示などで利用する際にはリストのIPv4アドレスを利用することが良いと思います。

  • 192.0.2.0/24 (TEST-NET-1)
  • 198.51.100.0/24 (TEST-NET-2)
  • 203.0.113.0/24 (TEST-NET-3)

まとめ

ip-ranges.jsonの存在は昔から知っていたのですが、AWSが所有するIPv4の総数は知らなかったので、7,000万個以上ものIPv4アドレスを所有していることに驚きました。

ip-ranges.jsonの変更をAmazon SNSで検知」-->「AWS Lambdaでリスト更新」。などの処理をしたことのある方はいると思いますが、今回のようにAWS所有のIPv4アドレス総数を調べる方はあまりいないと思います。

この記事がどなたかの助けになれば幸いです。

Discussion