はじめに
ルータやファイアウォールの設定の際に複数のサブネットを集約して、最小限のネットワークアドレスで表現したいことがあります。そんな時に必要となるスーパーネット化とかCIDR結合などと呼ばれる操作をPythonで簡単に行う方法があるので紹介します。
スーパーネット化
ネットワークスペシャリスト試験に出題された以下の問を題材にPythonを使ってスーパーネット化してみる。
問14 サブネットマスクが 255.255.255.0 である四つのネットワーク 192.168.32.0,192.168.33.0,192.168.34.0,192.168.35.0を,CIDRを使ってスーパーネット化したとき,ネットワーク番号とサブネットマスクの適切な組合せはどれか。
ネットワーク番号 サブネットマスク ア 192.168.32.0 255.255.248.0 イ 192.168.32.0 255.255.252.0 ウ 192.168.35.0 255.255.248.0 エ 192.168.35.0 255.255.252.0
出典:平成27年度 ネットワークスペシャリスト試験 午前Ⅱ 問14
・準備
必要なライブラリのインストール。
pip install netaddr
・スーパネット化
#便利なライブラリのnetaddrを読み込む
from netaddr import IPNetwork, cidr_merge
'''
問に記載されているネットワークアドレスをIPnetworkクラスに渡してsubnetsリストに格納。
(サブネット255.255.255.0はCIDR表記では/24。オクテット形式でも渡せる)
'''
subnets = [IPNetwork('192.168.32.0/24'),
IPNetwork('192.168.33.0/24'),
IPNetwork('192.168.34.0/24'),
IPNetwork('192.168.35.0/24')]
#たったこの1行だけでスーパーネット化できる!
merged_subnets = netaddr.cidr_merge(subnets)
print(merged_subnets)
・結果
この様にサブネットが192.168.32.0/22
に集約されてうまくスーパーネット化ができたことがわかる。
[IPNetwork('192.168.32.0/22')]
なお問14の解答群のサブネットマスクはオクテット表記となっているので、以下の様にCIDR表記のサブネットを求めると、
print(merged_subnets[0].netmask)
255.255.252.0
となるため、答えはイ(192.168.32.0/255.255.252.0
)であることがわかる。
2022/10/21追記:
@shiracamusさんのコメントにある通り、ipaddressライブラリでも同じことが出来ました。このライブラリは標準ライブラリに含まれていて、インストール不要なのでこちら方が使いやすいですね。
#@shiracamusさんのコメントから引用
from ipaddress import IPv4Network, collapse_addresses
subnets = [IPv4Network('192.168.32.0/24'),
IPv4Network('192.168.33.0/24'),
IPv4Network('192.168.34.0/24'),
IPv4Network('192.168.35.0/24')]
merged_subnets = [*collapse_addresses(subnets)]
print(merged_subnets)
[IPv4Network('192.168.32.0/22')]
さいごに
このnetaddrというライブラリはIPアドレスやネットワークアドレスに対する操作をするのにすごく便利なライブラリで、スーパーネット化だけでなく、さまざまな操作ができます。これまでにいくつか記事を書きましたので、そちらもご参照ください。
以上
参考サイト: