VPNクライアントが接続するとWebサーバーが消える
リクエストはLANに届き、応答はトンネルから出ていきます。ホストが何をすべきかに応じて、除外ルート、ポリシールーティング、または変換を選びます。
VPNクライアントが接続した瞬間に消えるサービスは、通常ブロックされているのではなく、間違ったインターフェースから応答しています。リクエストは物理NICに届き、デーモンが応答を書き、トンネルがデフォルトルートを引き継いでいるため、ルーティングテーブルはその応答をトンネルに渡します。リモートのクライアントは自分が開いた接続への応答を決して見ないので、待機したのちタイムアウトを報告します。その一連の流れのどこにもファイアウォールルールは関与していません。
症状:リクエストは入り、応答は間違った扉から出る
手がかりは、ホスト上の他のすべてが動いているのに受信接続だけが失敗することです。もう一つの手がかりは、LANからは到達できるがインターネットからは到達できないホスト、あるいはトンネルが再接続するまで動いてその後止まるホストです。いずれの場合も往路は正常で復路がそうではないため、ポリシーではなくルーティングの非対称性を示しています。
リクエストがどう届くかではなく、応答がどこへ行くかを見て確認してください。
物理インターフェースとトンネルデバイスの両方で同時にキャプチャします。リクエストが物理インターフェースに現れ、応答がトンネルに現れるなら診断は完了です。応答がどこにも現れない場合は、サービスが接続を一度も受け付けなかったということであり、別の原因による別の調査になります。
二つのデフォルトルートと一つのルーティング判断
デフォルトルートを設定するクライアントは、LANゲートウェイより良いメトリックを持つ二番目のエントリを追加します。代わりに半分の範囲のルートを二本入れるクライアントもあり、同じ空間をより具体的に覆って同じように検索に勝ちます。どちらの手法でも、通常の送信パケットはトンネルインターフェースを選びます。
その選択は宛先だけで決まります。カーネルはポリシールールに指示されない限り、パケットがどこから来たかを尋ねません。そのため公開クライアントアドレスへの応答はトンネルに渡され、その遠端は自分が持たない送信元アドレスのパケットを受け取り、それを捨てるか役に立たない場所へ転送します。Linuxでは厳格な逆経路フィルタリングが、あなたのサービスが目にする前に元のリクエストを落とすこともあり、外から見ると同じに見えます。どちらの症状も、受信フローとその応答の間の同じ欠けた関連から来ています。
トンネルは終始正しく振る舞っています。デフォルトルートを運ぶよう指示され、まさにそのとおりにしているのです。
トンネルを壊さずに戻り経路を直す
耐久性のある修復の形は三つあり、選択はホスト自身のトラフィックをどれだけトンネル内に残すべきかによります。サービスの宛先またはポートを除外するのが最小の変更です。送信元やマークによるポリシールーティングが最も正確です。送信元変換は最も粗く、二年後に説明するのが最も簡単です。
最初に見つけたスニペットではなく、ホストが何をすべきかで選んでください。
宛先の除外は安定した公開アドレスを持つサービスに向いており、デーモンをすべてのアドレスではなく物理アドレスに束縛するとその除外はより安全になります。送信元でテーブルを選ぶポリシールールは、ホスト自身の接続をトンネル内に保ちながら、サービスの応答をWANゲートウェイ経由で返します。応答をWANインターフェースでマスカレードすれば同じ経路に到達しますが、クライアントのアドレスがサービスのログから隠れるという代償があります。デフォルトルートの場当たり的な変更は、クライアントが再接続のたびにルートを書き換えるため、診断であって設定ではありません。
ip rule show
ip route get 203.0.113.9 from 192.0.2.44ホストが背後のLANのためにもルーティングする場合
さらに一段外側では、同じ非対称性がより多くの可動部品を伴って戻ってきます。トラフィックはインターネットからルーターに届き、内部デバイスへ転送され、そのデバイスの戻り経路はトンネルだけなので、応答はプロバイダー自身のアドレスから元のクライアントに届きます。すると接続追跡は、開始を見ていないフローへの応答に出会い、それを破棄します。クライアントはその間、何も見えません。
それを直すのは、受信接続が内部デバイスに届くようにする宛先変換と、そのデバイスの応答がルーター自身から来たように見える送信元変換の二つです。
ルーターファームウェアでは、通常の表現はポート転送をWAN側に固定し、ルーター自身のトラフィックはトンネルを通るというポリシールールです。送信元変換がなければ、その応答は外部クライアント宛てになり、内部デバイスにはそこへの経路がまったくありません。失敗する理由が異なるため、外から来る接続、ホスト自身が開始する接続、名前解決の三つを別々に試してください。