要約

  • IPv6 の限定スコープアドレスは、異なるゾーンで同じ値を使える。複数のゾーンに接続した端末は、128 ビットのアドレスとは別の zone index で出口を選び、その情報をパケットへ載せない。
  • RFC 6874 は 2013 年に ZoneID を URI に組み込もうとしたが、RFC 9844 は 2025 年にそれを実装困難として廃止した。現在の要求は、UI がローカルな識別子を入力・選択・検証し、OS のインターフェース番号へ変換することである。

仕様を戻すという前進

2025 年 8 月の RFC 9844 は RFC 6874 を完全に廃止した。ブラウザー実装者が URI 方式を実用にできないと判断したためであり、RFC 6874 が RFC 3986 に加えた更新も取り消した。検証済み erratum 8552 は、その更新関係がもはや存在しないことを記す。

新しい標準は別の場所へ義務を置く。グローバルユニキャスト以外のアドレスを受け取る UI は、利用者が zone identifier を入力または選択できなければならない。% を含む完全形が望ましいが、別フィールド、一覧、別の区切り、個別パラメーターも許される。

UI はアドレスと識別子を別々に保持し、後者をローカルインターフェース番号へ変換する。不正な識別子は、推測で補うのではなくエラーとして報告すべきである。POSIX の inet_pton() は fe80::1%eth0 全体を単独で変換できない。getaddrinfo() を使うか、文字列を分割して inet_pton() と if_nametoindex() を組み合わせる必要がある。

RFC 9844 はブラウザーが URI を取得する際の意味論を対象外にした。これは欠落ではなく、解ける問題を正確に限定した結果である。UI がローカル選択を受け付けることと、HTTP のグローバルな参照・origin を定義することは別の契約である。

入力を受ける側の責任

RFC 4007 は zone identifier の文字集合や長さを統一しなかった。柔軟性は OS ごとのインターフェース名を扱える一方、UI に検証責任を残した。RFC 9844 は適切な長さ制限を設け、NUL など危険な入力を拒否するよう求める。RFC 4007 の held erratum 8553 も、この欠けていた安全上の境界を RFC 9844 へ結び付けている。

入力は複数の解釈器を通る。フォーム、設定ファイル、シェル、URI 部品、ライブラリ、OS API がそれぞれエスケープや終端を扱う。途中の一層が値を二重にデコードしたり NUL で切ったりすれば、画面に表示した zone とカーネルへ渡した zone が違う可能性がある。

成功した接続の証明範囲も狭い。ある時点の端末で、入力名が一つのインターフェースへ対応し、その操作がその経路で成立したことは分かる。しかし相手の身元、アドレスの所有権、世界的な到達性、別端末での再現性は証明されない。ローカルな経路選択を認証材料へ昇格させてはならない。

ソケットは二つの値を受け取る

OS の API は最初からこの責任分担を表現していた。2003 年 2 月の RFC 3493 では、IPv6 ソケットアドレス構造体 sockaddr_in6 に sin6_addr と sin6_scope_id が別々に置かれる。前者は 128 ビットのアドレス、後者は 32 ビットのローカルな選択値である。

zone index はアドレスの末尾へ書き足されたビット列ではない。アプリケーションがローカルカーネルへ渡す付帯情報であり、IP パケットの宛先アドレスへ埋め込まれない。端末が複数の同一 scope zone に接続していなければ選択が自明なこともあるが、自明さはアドレスの一意性から生じるのではなく、その端末の接続条件から生じる。

RFC 3493 は、インターフェース名と番号の対応も定めた。if_nametoindex() は、与えられた名前をその OS 内のインデックスへ変換する。存在しない名前なら変換は失敗する。相手端末へ問い合わせたり、世界共通の名前空間を参照したりはしない。

このため en0、eth0、7 はそれぞれの端末における操作上の手掛かりであって、ネットワーク資源の恒久的な名称ではない。同じリンクの両端ですら、数値インデックスが一致する必要はない。

人が読むための % 記法

RFC 4007 は、曖昧さのないテキスト表現として <address>%<zone_id> を推奨した。実装は非負の十進数を扱うべきで、インターフェース名のような実装依存文字列を扱ってもよい。アドレス部分から scope が分かるので、後半の識別子は、その scope に属する zone の中で選べれば足りる。

ただし、この記法には明確な境界がある。グローバルアドレスに zone identifier を付けても意味がなく、ループバックへ使うべきでもない。そして文字列表現は一つのノード内だけで使う。解釈するすべてのノードが同じ意味を合意していない限り、ネットワーク上へ送ってはならない。

「表示できる」と「転送できる」を分けた点が重要である。UI、ログ、コマンドラインは、人がどの出口を選んだかを表す必要がある。しかし受信側にとって、送信側のインターフェース名は無関係であり、多くの場合は解釈不能である。

既定 zone への依存も移植性を保証しない。RFC 4007 は既定値を推奨し、通常はゼロで表すとしたが、RFC 9844 は Linux を含め、利用可能な既定 zone を持たない OS があると記録する。UI が選択を省略できた環境の成功例を、別環境の仕様にしてはいけない。

選択肢を示す画面

ノート PC が有線 LAN と保守用の別回線へ同時に接続され、どちらにも fe80::1 が見えているとする。利用者が管理画面を開こうとしても、アドレスだけではどちらのリンクか決まらない。ここで UI がインターフェースの選択肢を示すのは、親切な追加機能ではない。曖昧な入力を実行可能なローカル判断へ変える工程である。

RFC 4291 が定めるリンクローカルユニキャストは、一つのリンクで使うアドレスである。ルーターは、リンクローカルな送信元または宛先を持つパケットを別リンクへ転送してはならない。したがって二つのリンクで同じ数値が現れても、それだけで一つのグローバルな重複を意味しない。

RFC 4007 は、この状況を記述する語彙を整えた。scope は到達できるトポロジー領域の大きさ、zone はその scope に属する領域の一つの実体である。link-local scope は一種類でも、端末が接続するリンクごとに別の zone がある。

この区別がなければ、「リンクローカル」という性質と「右側のリンク」という選択が同じ語に押し込まれる。前者は共有できるプロトコル上の意味であり、後者は端末が自分の接続状態から決める事実である。

正規化できる部分と、できない部分

RFC 5952 は、IPv6 アドレスのテキスト表現を正規化した。ゼロ圧縮や英字の扱いを揃えることで、同じアドレスがログや設定で別物に見える問題を減らした。ポート番号と組み合わせる際の角括弧も整理した。

しかし、その規則は RFC 4007 の zone 拡張を対象にしない。RFC 9844 はこの点を明記する。アドレス部分を canonical にしても、インターフェース名は端末固有であり、数字インデックスは再起動やネットワーク名前空間によって意味が変わり得る。

監査記録で両者を一つの「正規 URL」へ潰すと、比較が簡単になる代わりに実行時の文脈が消える。逆に、文字列全体を恒久 ID として保存すると、ローカルな名前の偶然を資産識別へ持ち込む。保存すべきなのは、アドレス、入力された zone、解決されたインデックス、実行ホスト、時刻という分離された事実である。

URI の世界へ入ったローカル情報

問題は、アドレスを URI に記録しようとすると難しくなった。2005 年 1 月の RFC 3986 は URI をグローバルな識別構文として整理し、% をパーセントエンコーディングの開始記号とした。文字としてのパーセントをデータに含めるなら %25 と表す。

2013 年の RFC 6874 は、この文法の中へ ZoneID を置こうとした。HTTP URI の角括弧部分は [fe80::a%25en1] のようになる。%25 が zone 区切りの % を表し、その後ろがローカル名になる。

この案は、ブラウザーからリンクローカル機器へアクセスする使い方を整えようとした。しかし文書自身が、ZoneID は発信ノードだけで意味を持ち、外向き HTTP リクエストへ含める前に除去すべきだと述べていた。アドレスバーでは URI の一部に見える情報が、通信時には URI から消える。

その二重性は多くの判断を生む。履歴やブックマークには保存するのか。origin の比較に含めるのか。プロキシへ渡す前にどの段階で除くのか。%25 を一度だけ解くのか、別レイヤーが再び解くのか。文字列処理の小さな違いが、出口選択やセキュリティ境界の違いになり得る。

問題は zone identifier の必要性ではなく、それをグローバルな参照表現の内部へ置いたことだった。ホスト固有の引数に URI と同じ寿命、比較規則、共有範囲を与えると、どのレイヤーが意味を所有するかが曖昧になる。

パケットへ載せないことで成立する設計

zone identifier は、情報を増やすことで IPv6 を完成させたのではない。共有すべき情報とローカルに留める情報を分けることで、限定スコープを実用にした。scope の規則とアドレスは相互運用の対象であり、どのインターフェースを選ぶかは端末が自分の状態から決める。

UI の選択、API の二フィールド、カーネルのマッピング、IP 層の転送境界は一本の責任の鎖になる。どの段階でも、前段の成功を次段の保証と読み替えないことが大切だ。名前を受理したこと、番号へ変換したこと、パケットが送れたこと、相手が期待した主体だったことは、それぞれ別の証拠を要する。

画面が利用者に出口を選ばせる瞬間は、プロトコルの不足を隠す場面ではない。アドレスだけでは決まらないローカルな事実を、決められる場所で明示する場面である。手掛かりが端末内に留まるからこそ、ネットワーク上のアドレスは別端末の命名事情を背負わずに済む。

出典