/32 ホストルートが VPN エンドポイントの到達性を保つ理由
ホストルートはサブネットではなく一つのアドレスを選ぶ。トンネルのエンドポイントを到達可能に保ち、一つのリソースを固定できるが、アドレスが変わると古くなる。
接続後にルーティングテーブルを開くと、一つのアドレスだけがトンネル経由で流れ、その周囲のサブネットは依然としてローカルゲートウェイに向かっているのがわかる。そのエントリがホストルートだ。つまり一つのアドレスであり、すべて一のプレフィックスで一致する。ルーティングの判断は最長一致プレフィックスを使うため、/32 は /24 やデフォルトルートを変更せずに上書きできる点が重要だ。それが慎重な例外なのか将来の障害なのかは、どのアドレスを指し、誰が管理しているかで決まる。
一つのアドレス、テーブルに一つのエントリ
IPv4 のホストルートは /32 プレフィックスを、IPv6 のホストルートは /128 を持ち、エントリはちょうど一つの宛先アドレスに一致できる。テーブルの他の何も動かない。覆っているサブネットとデフォルトルートはそのままの位置に残る。狭いエントリがそのアドレスで勝つのは、後から追加されたからではなくプレフィックスが長いからだ。
この性質がホストルートを良い例外にも悪い習慣にもする。あるサービスの玄関を指す二つの /32 エントリは、その二番目のアドレスも、IPv6 アドレスも、来月移る先のアドレスも覆わない。説明のない単一アドレスのエントリで埋まったテーブルは、たいてい誰かがサブネットの判断を下す代わりにその周りを貼り続けてきたことを意味する。まずプレフィックス長を読み、次にそのエントリが何を守るのかを問うべきだ。
エントリをクライアントから外側へ読む
問題のあるマシンから始める。同じアドレスでもノート PC とその手前のゲートウェイでは経路が異なりうる。テーブルを上から読むのではなく、アプリが使う正確なアドレスに対してカーネルがどの経路を選ぶかを尋ねる。答えには インターフェースと次のホップ が含まれ、この二つが合わせて判断そのものだ。
ip route get 203.0.113.25
ip -6 route get 2001:db8:4::25
ip route show | grep -F 203.0.113.25
Find-NetRoute -RemoteIPAddress 203.0.113.25
アプリが実際に選ぶアドレスファミリーで問い合わせを繰り返す。クライアントは IPv6 を優先して IPv4 の例外を静かに迂回することがある。トンネルが上がる前と後で結果を比べ、両方の出力を残す。この比較で、クライアントが接続時にエントリを追加したのか、もともと存在していたのかがわかる。
永続エントリと実行時エントリは失敗の仕方が違う。実行時のものはセッションとともに消え、永続的なものは再起動を越えて残り、もう存在しないゲートウェイへトラフィックを送り続ける。
エンドポイントの例外と再帰の罠
VPN クライアントは通常、デフォルトルートを切り替える前に元のゲートウェイ経由で サーバーの外側アドレスへのホストルートをインストールする。そのエントリがなければ、暗号化されたパケットは構築しようとしているトンネルの中へ送られ、接続はタイムアウトするまでループする。
罠は、トンネルが受け入れるサブネットにたまたまそのエンドポイントアドレスが含まれるとき、または後から二つ目のプロファイルがより広いルートを追加するときに現れる。するとエンドポイントのエントリは長いプレフィックスに負け、トラフィックを流し始めた途端にセッションが崩れる。受け入れるサブネットの隣にエンドポイントアドレスを書くのが、利用者より先に衝突に気づく最も安価な方法だ。同じプロファイルがあるネットワークからは動き、別のネットワークからは失敗する理由もこれで説明できる。
アプリが実際に使う経路を確認する
アプリが別のアドレスや別のファミリーに接続する場合、ホスト名への ping の成功は弱い証拠にすぎない。クライアントを実行するマシンで、アドレス、ファミリー、ポート、インターフェースの正確な組み合わせを確認する。
ip route get 203.0.113.25
sudo nft list ruleset | grep -A 4 'chain output'
curl -sS --max-time 8 -o /dev/null -w '%{remote_ip}
' https://app.example.net
経路が間違っているなら、何かを編集する前に、要件がネットワークなのか一つのアドレスなのかを決める。単一アドレスの要件ならコメントと所有者を添えたホストルートで正当化できる。アドレスが回転するサービスにはドメインベースのルーティングか、正直なサブネットの判断が必要だ。
実際の宛先に対応しなくなったエントリを削除し、残すものは記録しておく。説明のない /32 は三か月後にはバグと区別がつかず、次の担当者は何が依存していたかを知らないまま削除してしまう。