Mímisbrunnr知恵の泉

← コンピュータネットワーク 一覧

🎓 レベル:標準 | 重要度:B(重要) 📎 前提:IPアドレスの基礎(IPv4)

要点(BLUF)

表記と短縮ルール

2001:0db8:0000:0000:0000:0000:0000:0001 は次の2段階で短くします。

  1. 各グループの先頭の0を削る → 2001:db8:0:0:0:0:0:1
  2. 連続する0グループを :: で1回だけ置換 → 2001:db8::1
import ipaddress
a = ipaddress.IPv6Address("2001:0db8:0000:0000:0000:0000:0000:0001")
print("compressed:", a.compressed)
print("exploded  :", a.exploded)

実行結果:

compressed: 2001:db8::1
exploded  : 2001:0db8:0000:0000:0000:0000:0000:0001

::1アドレスにつき1回だけ使えます(2回使うと0の個数が定まらないため)。

アドレスの構造とプレフィックス

一般的なユニキャストは、前半64ビットがネットワーク(プレフィックス)、後半64ビットがインターフェースIDです。IPv4の「ネットワーク部/ホスト部」に対応しますが、ホスト部が常に64ビットと広大なのが特徴です。

graph LR
  P["プレフィックス(前半64bit・/64)"]
  I["インターフェースID(後半64bit)"]
  P --- I

アドレス種別

種別範囲(プレフィックス)スコープ用途
グローバルユニキャスト GUA2000::/3インターネット全体公開アドレス(IPv4のグローバル相当)
ユニークローカル ULAfc00::/7(実質 fd00::/8)組織内私設(IPv4のプライベート相当)
リンクローカルfe80::/10同一リンク内のみ隣接通信・自動生成・必須
マルチキャストff00::/8範囲指定1対多(ブロードキャストは廃止)
ループバック::1自分自身IPv4の127.0.0.1相当

IPv6にはブロードキャストがなく、その役割はマルチキャストが担います(例 ff02::1 は全ノード)。リンクローカル(fe80::)はすべてのIPv6インターフェースに必ず1つ付き、近隣探索(NDP、ARPの後継)に使われます。

import ipaddress
# 注: 2001:db8::/32 は文書用に予約された範囲で is_private=True になる。
# ここでは実在のグローバルアドレス(Cloudflare DNS)で判定を示す。
for s in ["2606:4700:4700::1111", "fd00:abcd::1", "fe80::1", "::1"]:
    a = ipaddress.IPv6Address(s)
    kind = ("loopback" if a.is_loopback else
            "link-local" if a.is_link_local else
            "private/ULA" if a.is_private else
            "global")
    print(f"{s:20} -> {kind}")

実行結果:

2606:4700:4700::1111 -> global
fd00:abcd::1     -> private/ULA
fe80::1          -> link-local
::1              -> loopback

EUI-64 とSLAAC:自動でアドレスを作る

SLAAC(ステートレスアドレス自動設定)では、ルータが広告する**/64プレフィックスに、機器が自分でインターフェースIDを足して完成させます。インターフェースIDの古典的な作り方がEUI-64**で、48ビットMACから生成します。

手順:(1) MACを前半24bitと後半24bitに割り、間に FFFE を挿入、(2) 先頭バイトの7番目のビット(U/Lビット)を反転。

# MAC 00:1a:2b:3c:4d:5e から EUI-64 インターフェースIDを作る
mac = "00:1a:2b:3c:4d:5e".split(":")
b = [int(x, 16) for x in mac]
b[0] ^= 0b00000010                      # U/Lビットを反転
eui = b[0:3] + [0xFF, 0xFE] + b[3:6]    # 中央に FFFE を挿入
iid = "".join(f"{x:02x}" for x in eui)
iid = ":".join(iid[i:i+4] for i in range(0, 16, 4))
print("interface-id:", iid)
print("full address: 2001:db8:0:0:" + iid)

実行結果:

interface-id: 021a:2bff:fe3c:4d5e
full address: 2001:db8:0:0:021a:2bff:fe3c:4d5e

先頭が 00 から 02 に変わったのがU/Lビット反転の結果で、中央に ff:fe が挿入されています。現在はプライバシー上ランダムなインターフェースID(RFC 4941)も広く使われますが、EUI-64の仕組みはCCNAで問われます。

なぜIPv6へ移行するのか(設計の直観)

IPv4の32ビットは約43億で、世界の機器数に対し決定的に足りません。NATで延命してきましたが、NATは端点間の対等な接続(P2P)を壊します。IPv6の128ビット(約3.4×10の38乗)は枯渇の心配がなく、NATなしで端末ごとに公開アドレスを持てる世界へ戻します。アドレス自動設定(SLAAC)でDHCPなしでも繋がる手軽さも設計の狙いです。

⚠️ よくある誤解

対応 lab

関連