WireGuardクライアントが接続し、まったく別のインターフェース上のアドレスにpingすると、応答が返る。キャプチャには要求がトンネル上にしか現れない。壊れているものは何もなく、慎重に無効化した転送設定はこれと無関係だ。これは、図では似て見え、カーネル内ではまったく異なる二つの経路の比較である。

一方の経路は他人のためにパケットを転送し、もう一方はホスト自身に届ける。

ホスト宛のパケットはホスト内にとどまる

リモートクライアントは、ホストが持つアドレスにIPパケットを送る。ルーティングはそのパケットについて一つの問いを立てる。この宛先はローカルか。ホストが持つすべてのアドレスはローカルルーティングテーブルに現れ、そのテーブルはメインテーブルより先に参照されるので、パケットは別のインターフェースから出るのではなくホスト自身のスタックへ進む。応答はローカルで生成され、問い合わせがそこから来たためトンネルを通って戻る。

これが仕組みのすべてだ。転送は起こらず、インターフェース状態の変化も関与せず、問題のアドレスはどこか他の場所から到達可能である必要もない。

ip_forward が適用されない理由

転送は、到着したインターフェースとは別のインターフェースから出ていくパケットを扱う。ホスト自身へのpingはその経路を決して通らない。パケットはローカルで消費され、応答もローカルで生成される。したがって net.ipv4.ip_forward=0 を設定してもここでは何も変わらず、転送チェーンのルールがそのトラフィックを見ることもない。正しい制御は入力経路にあり、受信インターフェースや送信元で絞り込む。

だからこそ、転送を無効にしたうえでホストが隔離されているとみなすのは、誤った安心感を生む。

判断したローカルテーブルを読む

ip rule show は通常、優先度ゼロのルールですべての検索をまずローカルテーブルへ送ることを報告し、ip route show table local はホスト自身のアドレスをローカルスコープで一覧表示する。そのテーブルには、管理上ダウンしているが設定は残っているインターフェースのアドレスも含まれる。静的に割り当てられたIPv4アドレスは通常リンク断を生き延びるため、落ちたブリッジへのpingが依然として成功し、運用者を驚かせることがある。

IPv6はまさにこの点で異なる。リンクが落ちると、そのアドレスは通常取り下げられる。ただし keep_addr_on_down が設定されている場合は別だ。一つのルールが両方をカバーすると仮定せず、両者を比較してほしい。

ピアが実際に到達できるもの

セグメント上のルーター自身のアドレスからの応答は、そのセグメントの背後のマシンについて何も語らない。ピアはこの経路で別のインターフェースの背後のホストには到達できず、ルーター自身が持つアドレスにしか到達しない。ルーターのアドレスにpingするのではなく、別のLANホスト上のサービスを試すことが、転送がそもそも許可されているかを確かめる方法だ。

ピアをトンネルアドレスに束縛されたサービスに限定するのは入力ポリシーの問題である。望むサービスをトンネルインターフェースで許可し、それを使える送信元を制限する。パケットは実際にそこへ届くからだ。

廃止するつもりのアドレスも確認してほしい。インターフェースからアドレスを外すほうが、古いアドレスの上にファイアウォールルールを積み重ねるより確実だ。

関連記事