VPN アドレスにバインドしたアプリが誤ったルートを使い続ける理由
VPN アドレスにバインドしたソケットは通常のデフォルトルートをたどります。ポリシールールを追加する前に、アドレスの所有関係と送信元を意識した検索を確認してください。
アプリケーションが VPN のアドレスにバインドしても、接続は通常のデフォルトルートから出ていきます。バインド自体は何も失敗しておらず、バインドが行うことを正確に行っただけです。ソケットをローカルアドレスにバインドすると、カーネルがヘッダーに入れる送信元アドレスが選ばれます。ルートをインストールするわけでも、その送信元を持つパケットを特定のトンネルへ送るポリシールールを作るわけでもありません。
このランブックの残りは、私が使っている確認の順序と、各観察を得るコマンドです。
バインドが実際に決めること
バインドはソケットにローカルアドレスを割り当てます。その後カーネルは、ポリシールールが検索に使うテーブルを変えない限り、通常と同じルート検索を実行します。
そのため、パケットが物理インターフェース上で VPN の送信元アドレスを付けて出ていくことがあります。反対側では、ネットワークがその経路で想定していないプライベート範囲から到着し、戻りのトラフィックには戻るルートがなく、接続は停止するかリセットされます。
Linux の IP ソケットのリファレンスがバインドの意味を説明しています。ルーティング側は ip-rule と ip-route にあり、これらが別のマニュアルなのには理由があります。
アドレスがこのネットワーク名前空間に属することを確認する
バインドできるアドレスは、アプリケーションが動作するネットワーク名前空間内のインターフェースに存在していなければなりません。ピアのアドレス、ゲートウェイのアドレス、別の名前空間にしか存在しないアドレスはバインドできず、呼び出しは EADDRNOTAVAIL で失敗します。
ip -br addr show
ip netns identify <pid>
ss -tanp | grep <port>その三つをアプリケーションと同じコンテキストで実行します。同じ名前空間で、可能なら同じユーザーです。古い net30 の図は、現在のトポロジがクライアントにどのアドレスを割り当てたかの証拠にはなりません。実際に有効なインターフェースを読んでください。
その送信元と宛先の検索を読む
一つのコマンドが、バインドが答えなかった問いに答えます。
ip route get 203.0.113.10 from 10.8.0.2
ip rule show最初の行は、その送信元からその宛先へ向かうパケットがたどるルートを、出力インターフェースと優先送信元を含めて表示します。物理インターフェースが示されるなら、バインドとルートは食い違っており、パケットは戻れない送信元で出ていきます。
続いて ip rule show が、別のテーブルを選ぶルールがあったかどうかを教えます。ここでは優先度が重要です。最初に一致したルールが勝ち、自分のルールより上にある包括的なルールは自分のルールを見えなくします。
ポリシールールはそれが設計である場合にだけ入れる
送信元ベースのルーティングは意図的な設計であり、一つのアプリの修理ではありません。ポリシーの所有者がトンネルのサブネットからのトラフィックにトンネルを使わせたいなら、ルールはその所有者の設定に属し、手元のノート PC での一時的なコマンドに属するものではありません。
実用的な形は、トンネル経由のデフォルトルートを持つ専用テーブルと、VPN の送信元範囲をそのテーブルへ送るルールです。設計に必要な例外を追加してください。トンネルのデフォルトだけを持つテーブルは、ローカルに残すべき宛先や物理経路で届くべき宛先まで取り込んでしまいます。
ip route add default dev tun0 table 100
ip rule add from 10.8.0.2 table 100 priority 100
ip route get 203.0.113.10 from 10.8.0.2ip rule del と ip route flush table 100 で戻します。この方法で追加したものは、管理者が書き込まない限り再起動で消えます。これは安全上の性質であり、唯一のコピーをシェルの履歴に置かない理由でもあります。
三つの観察で検証する
アプリケーションが要求した送信元、検索が選んだルート、サーバーが実際に見た送信元を記録します。
この三つは食い違うことがあり、食い違いはそれぞれ別の場所を指します。トンネルのインターフェースでのキャプチャは、パケットが正しい送信元で出たことを証明します。物理インターフェースでのキャプチャは、間違った経路で出たことを証明します。経路を端から端まで証明できるのはサーバー側の視点だけです。
アプリケーションがデバイスへのバインドオプションやアプリごとのルーティングモードを提供しているなら、別の制約を持つ別の仕組みとして扱ってください。見た目が似た設定がすべて同じカーネルの判断に至るわけではありません。