IPレンジの集約スクリプト


細切れレンジで困ること

アクセスログの分析であったり、接続制限のためのAccessListであったり、あるサービスが使用するIPレンジをまとめて使えるようにしておく、というのが必要になることが多々あります。

有名所のサービスであれば、自身が使うIPアドレスレンジをきちんと公開してくれているものなのですが、、結構細切れになっていることがあります。

例えば、googleは非常にシンプルに集約した状態で情報公開してくれているのですが、Microsoftは凄まじいことに。。
2021/8/1時点の公開情報で見てみると、googleの71レンジに対して、MSは実に47,602レンジ!!
サービスやリージョンごとの詳細な使い分けの情報をつけて公開してくれているからですね。
じっくりデータを分析するときはありがたいのですが、リアルタイムで処理させる用途で使うには重すぎ。
レンジをちゃんと集約してやる必要があります。
https://www.gstatic.com/ipranges/goog.json
https://www.microsoft.com/en-us/download/confirmation.aspx?id=56519

IPアドレス集約サービス

軽くググると、IPレンジのリストを放り込むと集約後のデータを返してくれるサービスやスクリプトというものもあります。
https://tehnoblog.org/ip-tools/ip-address-aggregator/
https://github.com/lamehost/aggregate-prefixes/

ただ、まぁいつもどおり、Webサービスは「コレ提供してるの誰、、?」という問題がつきまといますし、取り回しがしにくいです。
スクリプトの方はシンプルで良さげですが、せっかくなら雑にレンジ集約する機能も作り込みたいので、自分で実装してみることにします。

作ってみたもの

こんな。

サンプルとして、IPレンジを公開しているgoogle, Microsoft, AWS, Digital Oceanについてはデータのダウンロードから集約までを実施するサンプルスクリプトもつけておきました。

但し、パスを通す実装にきちんとしてないので、実施時には頭にenvをつけて実行して、PHTHONPATHとして該当gitをDLしてきたフォルダを追記してください。
以下の例ではHOME直下にDLしてきた場合の想定です。

使ってみると

試しにmicrosoftのレンジを集約してみます。

% env PYTHONPATH="${PYTHONPATH}:${HOME}/iptools-nfw" python3 ${HOME}/iptools-nfw/examples/microsoft.py
Check latest URL and input:
https://www.microsoft.com/en-us/download/confirmation.aspx?id=56519
input:https://download.microsoft.com/download/7/1/D/71D86715-5596-4529-9B13-DA13A5DE5B63/ServiceTags_Public_20210913.json
IPv4, original: 37487, aggregated: 1288
IPv6, original: 11174, aggregated: 375

マイクロソフトのIPアドレス一覧のURLは動的に変わるかもしれませんので、都度確認してください。
今回の例だと、IPv4で生だと37,487レンジ、集約すれば1,288レンジになります。
。。。3万7千レンジの管理は流石にゾッとします。。千二百も大概ですけれど。

もっと使ってみると

今回せっかくなので実装してみた「雑な集約」を走らせてみます。

% python3 ~/iptools-nfw/ipaggr.py -m 500 ./microsoft_ipv4.txt | sort > ./ms_aggr.txt  

小さいレンジから順に、連続しているレンジがなくても集約してしまう(192.168.0.0/32だけリストにあり、192.168.0.1/32が無い場合でも、192.168.0.0/31に置き換えてしまう)というのを繰り返して、レンジの合計数が500以下になるまで続ける、ということをします。

./ms_aggr.txtのなかの、Aggregatedの部分が欠落しているレンジが集約された結果、Missingsが存在しない分のレンジ群です。
2021/9/19に実行すると集約結果の1つに"102.133.0.0/16"というレンジが出来上がるのですが、雑集約前のレンジと見比べて見ると以下のようになります。

# 雑集約前
102.133.0.0/18
102.133.112.0/28
102.133.120.0/21
102.133.128.0/18
102.133.192.0/19
102.133.224.0/20
102.133.240.0/25
102.133.240.128/26
102.133.248.0/21
102.133.64.0/19
102.133.96.0/20

# Missings
102.133.112.128/25
102.133.112.16/28
102.133.112.32/27
102.133.112.64/26
102.133.113.0/24
102.133.114.0/23
102.133.116.0/22
102.133.240.192/26
102.133.241.0/24
102.133.242.0/23
102.133.244.0/22

そもそもwhoisで確認すると、102.133.0.0/16はまるごとMicrosoftのレンジですが、サービス用途割り当てる分とそれ以外(未割り当てか、MSの他の機能用途か)が結構入り混じってます。
ある程度想定外が混ざることに目をつむってでもレンジ数を下げたいときには使ってみてください。

ちなみに-m 50まで行くと、全然別のISPのレンジなどがかなり入り混じったリストになります。

実装してみての色々

集約の際に、「最長prefixを制限する」といような機能は今の所作ってません。
例えば/32がたくさんのファイルに対して、全て/24より大きなまとまりに束ねてしまう、というような実装です。
コレをやるとレンジが集約されて、総レンジ数が少なくなってくれる、、ような気がするのですが、実はそうでもないんですね。
/24ごとに1IPずつしかつかってない、みたいなリストも少なくないので、/24に集約してもレンジの総数が変わらない("192.168.0.1/32"の1レンジが"192.168.0.0/24"に置き換わるだけ)ということが起こります。

但し、機器によって登録できるprefixサイズが固定というような悲しい実装の機器やサービスもありそうな気がしますので、そのうちprefix指定で圧縮する機能も作っときます。

あと、雑集約のときにAS番号が同一なら許可する、というような機能は実装しても面白いかもしれませんね。
自分の用途で使ってみて、ちょこちょこいじってみようかと思います。

とりあえず今のところはそんなで。