【実務・中級編】 IPv6リンクローカルアドレスの自動生成(EUI-64) – ネットワーク基礎とWebセキュリティ実践ガイド

ネットワークの「素顔」を暴く:EUI-64とプライバシー拡張が教えるIPv6の光と影

ネットワークエンジニアとして現場に立っていると、「IPv6って結局、自動で繋がるんでしょ?」という声をよく耳にします。確かに、ルーターのポートにケーブルを挿せば、そこには魔法のように通信が確立される。だが、その裏側で何が起きているのか。今日は、IPv6の根幹を支える「リンクローカルアドレスの自動生成(EUI-64)」と、それが抱える「プライバシー上の爆弾」、そして現代のWeb API運用における落とし穴について、現場の視点から紐解いていく。

—

EUI-64:MACアドレスから「身分証明書」を錬金する

IPv6のインターフェースIDを生成するもっとも古典的かつ強力な手法が EUI-64 だ。48ビットのMACアドレスを、64ビットのIPv6インターフェースIDに変換するこの仕組みは、シンプルゆえに美しい。

EUI-64の生成ロジック(現場の暗黙知)

仕組みはこうだ。まず、MACアドレスの中央に 0xfffe という16ビットの値をぶち込む。次に、第7ビット(U/Lビット)を反転させる。なぜ反転させるのか? それは「このアドレスがユニーク(ユニバーサル)であることを示すため」だ。

例えば、MACアドレスが 00:1a:2b:3c:4d:5e だとしよう。

1. 挿入: 00:1a:2b + ff:fe + 3c:4d:5e
2. 反転: 00(バイナリ 0000 0000)の第7ビットを反転 → 02(0000 0010)
3. 完成: 021a:2bff:fe3c:4d5e

これが、あなたのPCが自律的に名乗るインターフェースIDとなる。この「MACアドレスから一意のアドレスが生成される」という特性が、インフラ屋にとってはトラブルシューティングの強力な武器になる。「このパケットの送信元は誰だ?」という問いに対し、ログに記録されたIPv6アドレスを見れば、即座にMACアドレス、ひいてはベンダーやハードウェアの特定まで辿り着けるからだ。

—

なぜ「プライバシー拡張」が必要なのか?

しかし、このEUI-64には致命的な弱点がある。MACアドレスから生成されるということは、「世界中のどのネットワークに移動しても、同じインターフェースIDを使い続ける」ことを意味する。

想像してほしい。あなたがカフェのWi-Fiから社内LAN、そして出張先のホテルへと移動するたびに、同一の「足跡(インターフェースID)」を撒き散らしているとしたら? 悪意のあるトラッカーにとって、これほど追跡しやすいターゲットはない。Web APIのログに常に同じIPv6アドレスが残ることは、ユーザの行動履歴を紐付ける鍵となってしまう。

そこで登場するのが RFC 4941 で定義された「プライバシー拡張(Privacy Extensions)」だ。

プライバシー拡張の挙動

OSは、一定時間ごとにランダムなインターフェースIDを生成し、それを一時的なアドレス(Temporary Address)として通信に使用する。これにより、外部からは同一ホストかどうかの判別が困難になる。現代のOS(Windows, macOS, Linux)では、これがデフォルトで有効だ。

—

実務で役立つ確認コマンドとデバッグ手法

ネットワークの現場では、「なぜAPIへのリクエスト元IPが変わるんだ?」という問い合わせがよくある。これは多くの場合、このプライバシー拡張が原因だ。

Linuxで現在のアドレスを確認する

ip addr コマンドを叩くと、その挙動がはっきりと見て取れるはずだ。

# インターフェースのIPv6アドレスを確認
ip -6 addr show eth0

出力結果の中に、scope global と表示されるアドレスが複数存在し、一方は mngtmpaddr (Managed Temporary Address)、もう一方は noprefixroute などとフラグが立っているはずだ。

Pythonでローカルのアドレスを識別する

Web APIのクライアントサイドで「どのアドレスを使って通信しているか」をログ出力したい場合、以下のコードが役立つ。

import socket

def get_ipv6_addresses():
    # ホスト名を解決して全アドレスを取得
    addr_info = socket.getaddrinfo(socket.gethostname(), None, socket.AF_INET6)
    for info in addr_info:
        # info[4][0] がIPv6アドレス
        print(f"利用可能なIPv6アドレス: {info[4][0]}")

# 実際にどのアドレスで通信するかはOSのルーティングテーブルに依存する
get_ipv6_addresses()

—

運用上の注意点:API設計とセキュリティの境界

最後に、Web APIを設計・運用するエンジニアへ忠告がある。

1. IP制限の罠: 「IPv6アドレスでアクセス制限をかける」という設計は、もはや過去のものだ。プライバシー拡張により、同一クライアントでもIPが頻繁に変わる。認証には Authorization ヘッダー(JWTなど)やセッションIDを使うのが鉄則だ。
2. ログ解析の複雑化: ログ解析を行う際、1つのIPv6アドレス = 1ユーザー とみなすロジックは必ず破綻する。プライバシー拡張を考慮し、ユーザーIDとIPを紐付ける際は、生存期間を考慮した設計を心がけてほしい。
3. パケットキャプチャの泥臭さ: もし通信トラブルが発生したら、tcpdump で icmp6 をフィルターして追いかけてみてほしい。Neighbor Solicitation や Router Advertisement がパケットの中に蠢いているのを見れば、OSがどのようにアドレスを生成し、DAD(重複アドレス検出)を行っているかが手に取るようにわかるはずだ。

ネットワークは生き物だ。EUI-64という「固定のアイデンティティ」と、プライバシー拡張という「流動的な匿名性」。このバランスの上に、今日のセキュアなインターネットは成り立っている。教科書を閉じて、ぜひ自分のPCのパケットを眺めてみてほしい。そこには、OSが自らの意思でアドレスを生成し、ネットワークと対話するリアルな息吹があるはずだ。

コメント

タイトルとURLをコピーしました