2026年8月16日

2026年8月16日

スーパーネット(経路集約)を確認するツールと手順|Python・ipcalc・ルーターでの検証

スーパーネット(経路集約)が正しいかどうかは、「まとめた範囲に含めたいネットワークがすべて入っているか」と「含めてはいけないアドレスが混ざっていないか」の2点を確かめれば判断できます。この記事では、Python の標準ライブラリ ipaddress、Linux の ipcalc などのコマンド、ルーター側の経路表を使って、スーパーネットを計算・検証する手順を解説します。設定を入れる前の机上チェックと、設定後の動作確認の両方ができるようになります。

スーパーネットとは何か

スーパーネットは、連続した複数のネットワークを、より短いプレフィックス長の1つのネットワークとして表したものです。たとえば次の4つは、まとめて 192.168.0.0/22 と書けます。

  • 192.168.0.0/24
  • 192.168.1.0/24
  • 192.168.2.0/24
  • 192.168.3.0/24

ルーターの経路表やファイアウォールのルール、BGP で外部に広告する経路を短くできるのが利点です。一方で、まとめ方を誤ると、自分が使っていないアドレスまで「こちらに送ってよい」と宣言することになり、通信の吸い込みやループの原因になります。だからこそ、設定前にツールで検証する価値があります。

集約できる条件を先に押さえる

ツールの結果を読むために、集約が成立する条件を3つ確認しておきます。

  1. アドレスが連続している: 192.168.0.0/24 と 192.168.2.0/24 だけでは、間の 192.168.1.0/24 が抜けるため、/23 や /22 にまとめると余計な範囲を含みます。
  2. 個数が2のべき乗になっている: /24 を2つなら /23、4つなら /22 です。3つの /24 は1つのプレフィックスでは過不足なく表せません。
  3. 先頭が境界にそろっている: /22 の先頭は第3オクテットが4の倍数(0, 4, 8…)である必要があります。192.168.1.0〜192.168.4.255 は /24 が4つ連続していても、先頭が境界にないため1つの /22 にはなりません。

3つ目は見落としやすく、手計算での誤りの多くがここで起きます。ツールを使う最大の理由は、この境界チェックを機械に任せられる点です。

Python の ipaddress で計算・検証する

Python 3 が入っていれば追加のインストールなしで使えます。Windows・macOS・Linux のどれでも同じ結果になるため、チームで手順を共有するときにも向いています。

まとめられるかを試す

collapse_addresses() は、渡したネットワークのうち、隣接していて集約できるものをまとめて返します。

import ipaddress

nets = [ipaddress.ip_network(n) for n in [
    "192.168.0.0/24", "192.168.1.0/24",
    "192.168.2.0/24", "192.168.3.0/24",
]]
print(list(ipaddress.collapse_addresses(nets)))
# [IPv4Network('192.168.0.0/22')]

結果が1つのネットワークになれば、過不足なく1本の経路にまとめられます。2つ以上返ってきた場合は、連続していないか、境界がそろっていないかのどちらかです。

候補のスーパーネットを検証する

すでに「この範囲でまとめたい」という候補があるときは、含まれていないネットワークと、候補の中で誰も使っていない残りの範囲を洗い出すと判断しやすくなります。

import ipaddress

def check_supernet(candidate, subnets):
    sup = ipaddress.ip_network(candidate)  # 境界がずれていれば ValueError
    subs = list(ipaddress.collapse_addresses(
        ipaddress.ip_network(s) for s in subnets))

    outside = [s for s in subs if not s.subnet_of(sup)]
    remaining = [sup]
    for s in subs:
        if not s.subnet_of(sup):
            continue
        nxt = []
        for r in remaining:
            if s.subnet_of(r):
                nxt.extend(r.address_exclude(s))
            elif not r.subnet_of(s):
                nxt.append(r)
        remaining = nxt

    print("候補:", sup)
    print("候補に入っていないネットワーク:", outside or "なし")
    print("候補内で未使用の範囲:", sorted(remaining) or "なし")

check_supernet("192.168.0.0/22",
               ["192.168.0.0/24", "192.168.1.0/24", "192.168.3.0/24"])

この例では「未使用の範囲: 192.168.2.0/24」と表示されます。未使用の範囲が残る集約は、その範囲宛ての通信も自分の側に引き込むことを意味します。意図して予約している範囲なら問題ありませんが、他拠点や他社が使っている範囲なら集約をやめるか、範囲を分けて広告します。

ip_network("192.168.1.0/22") のように境界からずれた指定をすると、ValueError(host bits set)で止まります。これは誤りに気づかせてくれる動作なので、strict=False で黙らせる前に、本当にその範囲でよいか見直してください。strict=False を付けると、ホスト部を0にした 192.168.0.0/22 として扱われます。

連続していない範囲を覆う最小のブロックを探す

「とりあえず全部を覆う最小のプレフィックスを知りたい」という場合は、プレフィックス長を1ずつ短くして、すべてを含むところで止めます。

import ipaddress

def smallest_cover(subnets):
    nets = [ipaddress.ip_network(s) for s in subnets]
    cand = nets[0]
    while not all(n.subnet_of(cand) for n in nets):
        cand = cand.supernet()
    return cand

print(smallest_cover(["10.1.4.0/24", "10.1.9.0/24"]))  # 10.1.0.0/20

結果は「全部を含む」というだけで、余分な範囲を多く含むことがあります。経路として使うかどうかは、前の検証関数で未使用の範囲を確認してから決めます。

コマンドラインツールで確認する

Linux では ipcalc や sipcalc が手軽です。ただし、ipcalc は配布元によって別のプログラムが同じ名前で入っている点に注意が必要です。Debian・Ubuntu 系の ipcalc と、Red Hat・Fedora 系の ipcalc ではオプションや出力形式が異なります(2026年10月現在)。

# Debian/Ubuntu 系(apt install ipcalc)
ipcalc 192.168.0.0/22

# 範囲を CIDR ブロックに分解する(Debian/Ubuntu 系の ipcalc の機能)
ipcalc 192.168.0.0 - 192.168.3.255

1行目では、ネットワークアドレス、ブロードキャスト、利用できるホストの範囲が表示されるので、集約後の範囲が想定どおりかを目で確かめます。2行目の範囲指定は、開始と終了のアドレスを最小個数の CIDR ブロックに分解する機能で、1ブロックで返れば過不足なく集約できる範囲です。手元の ipcalc で同じ書き方が使えない場合は、ipcalc --help で使えるオプションを確認するか、前述の Python を使ってください。

設定後はルーターの経路表で確かめる

計算が合っていても、実際にどの経路が選ばれるかは機器で確かめます。経路は「最も長く一致するプレフィックス(最長一致)」が優先されるため、集約経路と個別経路が両方あると、個別経路が使われます。

# Linux: 宛先ごとに実際に選ばれる経路を表示
ip route get 192.168.2.10

# 経路表の一覧
ip route show

ip route get は、指定した宛先に対してカーネルが選ぶ経路を1行で示します。集約経路だけを入れたつもりでも、古い個別経路が残っていれば、そちらが表示されます。

集約経路の範囲内で未使用の部分がある場合、その宛先の通信が上流と行き来してループすることがあります。これを防ぐため、集約を広告する側でその範囲を破棄する経路を置くのが一般的です。

# 集約範囲に一致したが個別経路が無い通信を破棄する
sudo ip route add blackhole 192.168.0.0/22

FRRouting などで BGP を運用している場合は、aggregate-address で集約経路を作り、show ip bgp で広告される経路を確かめます。summary-only を付けると個別経路の広告が抑止されますが、相手側の経路制御に影響するため、変更前に現在の設定を保存し、検証環境か影響の小さい時間帯で試してください。

よくあるつまずき

  • 境界のずれ: 先頭アドレスがプレフィックスの倍数になっていない。Python の ValueError や ipcalc の分解結果で気づけます。
  • 抜けを含んだ集約: 個数が足りないまま短いプレフィックスにする。未使用範囲の洗い出しで確認します。
  • 他者の範囲を含む広告: 社外や他拠点に広告する経路で起きると、影響が自社の外に及びます。広告前に、未使用範囲が本当に自分の管理下か確認します。
  • IPv4 と IPv6 の混在: Python の collapse_addresses() は同じバージョン同士でしか使えません。混ざっていると TypeError になるため、分けて処理します。

まとめ

  • スーパーネットの確認は「必要な範囲がすべて入っているか」「不要な範囲が混ざっていないか」の2点で判断する
  • 集約の条件は、連続していること、個数が2のべき乗であること、先頭が境界にそろっていること
  • Python の ipaddress は OS を問わず使え、collapse_addresses() と address_exclude() で集約可否と未使用範囲を調べられる
  • ipcalc は配布元で中身が違うため、使えるオプションを手元で確認する
  • 設定後は ip route get などで実際に選ばれる経路を確かめ、未使用範囲は破棄経路で吸い込みを防ぐ

お気軽にご相談ください

お見積りへ お問い合わせへ
▲