いつもの LINE オープンチャットに投稿された質問です。
IP アドレスのネットワークの引き算?の仕方を考えているのですが、
192.168.0.0/24 というネットワークがあった場合、
一部サブネットだけ取り除いた場合の、最適解の結果を出力させたいです。
ex1)192.168.0.0/25を取り除きたい
→192.168.0.128/25
ex2)192.168.0.32/28を取り除きたい
→192.168.0.0/27
→192.168.0.48/28
→192.168.0.64/26
→192.168.0.128/25
のような感じで出力させたいのですが、何かいい方法ないでしょうか。。。
以前、ネットワークエンジニアをやっていて、私も気になり、少し調べてみたところ、ドンピシャなライブラリを見つけたので、ご紹介します。
netaddr
netaddr というライブラリです。
外部ライブラリなので pip
などでインストールします。
pip install netaddr
質問に対する解答
質問の内容は netaddr を使うと簡単に書くことができます。
ex1)
from netaddr import *
result1 = IPSet(['192.168.0.0/24']) - IPSet(['192.168.0.0/25'])
for nw in result1.iter_cidrs():
print(nw)
192.168.0.128/25
ex2)
from netaddr import *
result2 = IPSet(['192.168.0.0/24']) - IPSet(['192.168.0.32/28'])
for nw in result2.iter_cidrs():
print(nw)
192.168.0.0/27
192.168.0.48/28
192.168.0.64/26
192.168.0.128/25
下記のようにiter_cidrs()
メソッドを使わずに for 文を回すと、IPアドレス1個単位で出力されます。
from netaddr import *
result3 = IPSet(['192.168.0.0/24']) - IPSet(['192.168.0.0/25'])
for nw in result3:
print(nw)
192.168.0.128
192.168.0.129
192.168.0.130
〜省略〜
192.168.0.253
192.168.0.254
192.168.0.255
netaddr でできること
質問の内容以外で、netaddr でできることをいくつかご紹介します。
IPアドレスの種類を判定
プライベートIPアドレスかどうかを判定することができます。
from netaddr import *
print(IPAddress('192.168.1.2').is_private())
print(IPAddress('182.22.16.251').is_private())
print(IPAddress('fe80::889:fc6a:2ebb:4f14').is_private())
print(IPAddress('2404:6800:4004:812::200e').is_private())
True
False
True
False
IPv6にも対応しています。
ネットワークアドレスを調べる
IPアドレスをサブネットマスク から ネットワークアドレスを調べることができます。
from netaddr import *
ip = IPNetwork('192.168.100.100/21')
print(ip.network)
192.168.96.0
Google Colaboratory
本記事に掲載しているコードは Google Colaboratory で動作を確認しています。
下記リンクからアクセスして、ご自身の Google ドライブにコピーしていただければ、すぐに実行できます。
環境構築の不要な Google が提供している Webサービスなので、Python を学習中の方にはオススメです。
おわりに
今回は、ネットワークアドレスを表現および操作するためのライブラリ netaddr をご紹介しました。
ネットワークエンジニアをやっていたころは Python を知らなかったのですが、Python はライブラリが豊富なので、色々使えたな〜と今頃になって思います。
検証だったり、変更作業前後の動作確認だったり、監視やログの収集、コンフィグ作成の自動化とか、すぐに思いつくものでも沢山ありますね。
機会があれば、netaddr 以外のネットワーク関連のライブラリも紹介したいと思います。
以上です。
コメント