ルーティングテーブルのダンプは、VPNのトラブルシューティングで最も役に立たない診断であり、最も頻繁に貼り付けられるものです。四十行のプレフィックスは、マシンが何をできたかを示すだけで、失敗した要求に対して何をしたかは示しません。本当に必要な仕組みはルックアップです:この送信元とこの宛先が与えられたとき、どのルールが一致し、どのテーブルが参照され、どのインターフェースとネクストホップが出てきたのかを突き止めることです。一つの宛先と一つの送信元から始め、その問いを手にテーブルを読めば、同じ出力がノイズではなく証拠になります。

テーブルは候補の集合であり、決定ではない

各エントリは、プレフィックスと、それに一致するトラフィックをどう扱うか(インターフェースへ送る、ネクストホップへ渡す、あるいは破棄する)を記述します。その一覧は意図で並べられておらず、人間にとって最も具体的に見えるエントリが常にカーネルが選ぶものとは限りません:選択は最長プレフィックス一致に従い、同じプレフィックスの中ではメトリックに従うからです。

したがって最初の一手は、一覧を読むのではなくカーネルに尋ねることであり、ルックアップコマンドは宛先について答え、送信元引数を付けると、転送された接続やバインドされた接続が使う正確な組について答えます。

ip route get 198.51.100.10
ip route get 198.51.100.10 from 10.80.0.25
ip -6 route get 2001:db8:10::40

上記の各アドレスはドキュメント用の例です。要点は答えの形です:インターフェース、選ばれた送信元アドレス、ゲートウェイ、そしてエントリの由来したテーブル。その出力が期待したインターフェースと一致しなければ、一つのコマンドで問題を特定できたのであり、テーブル全体をいくら読んでもどの候補が勝ったかは分からなかったでしょう。

ルックアップはまずルールを通り、次にテーブルを通る

Linuxでは決定は二段階です。ポリシールールは優先順に評価され、最初に一致したルールが参照するテーブルを名指しし、そのテーブルが最長プレフィックス一致を行います。ルールは送信元、宛先、ファイアウォールマーク、インターフェース、またはその組み合わせで一致でき、だからこそメインテーブルのダンプは完全に正確でありながら、調査中のパケットにはまったく無関係であり得ます。

ip rule show
ip route show table all | head -40
ip route show table 100

ルールがVPNプールからのトラフィックをテーブル100へ送るなら、重要なのはテーブル100であり、 メインテーブルはおとりです。これはルーター上の送信元ベースルーティングの仕組みでもあります:同じ宛先でもパケットの出所によって二つの異なる答えがあり得て、送信元引数付きのルックアップだけがどちらが適用されるかを明らかにします。

IPv6には独自のルールとテーブルがあります。両方のファミリーを動かす設計には両方のルックアップが必要で、動くIPv4の答えは、デュアルスタックのクライアントが好むかもしれないv6の経路について何も語りません。

VPNクライアントがインストールするもの

クライアントは通常、デフォルトルートを置き換えません。なぜなら、それをするとトンネル自身の外側の経路が壊れるからです。代わりに、プレフィックス長で勝つより具体的なもので、0.0.0.0/1と128.0.0.0/1を覆う一対の半分デフォルトが古典的な手法です:どちらも0.0.0.0/0より長いプレフィックスで、合わせて全空間を覆い、特定のプライベートプレフィックスにポリシールールを加えるものもあれば、選択したトラフィックだけを捕まえるためにマークを付けるものもあります。

だから「VPNがデフォルトルートを変えなかった」は失敗の証拠ではありません:実際に何を追加したのか、問題の宛先がそのプレフィックスに入るのかを確認してください。

ip route show | grep -E 'tun|wg|ppp|ipsec'
ip route get 10.20.30.40 from 10.80.0.25

二つの半分ルートはデフォルトに見えないため、ダンプでは見落としやすく、プレフィックスの追加を忘れたスプリットトンネル設定は、まさに追っている症状を生みます:トンネルを使うべきアプリケーションが、代わりにローカルで名前解決して接続してしまうのです。インストールされたプレフィックスを、たまたま試したアドレスではなく、ユーザーが実際に必要とする宛先と比べてください。ファイルサーバーを覆うがそのリゾルバーを覆わないスプリットトンネル一覧は、公開アドレスに解決してから認証に失敗する接続を生みます。これはパスワードの問題に見えて、経路の問題です。

外側の経路も生き残らなければならない

トンネル自体がトラフィックです。カプセル化されたペイロードを運ぶパケットは物理インターフェースを通ってピアのアドレスへ行き、その経路がトンネルへ戻ってルーティングされてはなりません。そうなると、トンネルが確立した後にトラフィックを通さなくなるという特徴的な障害が起きます:トンネルの輸送が今やトンネルの内側にあるからです。

ピアのアドレスを、内側の宛先を確認したのと同じ方法で確認し、トンネルではなく物理インターフェースに解決することを確かめてください

ip route get 203.0.113.10
traceroute -n -m 5 203.0.113.10

再帰ルート、ピアを捕まえるポリシールール、フルトンネルクライアントに置き換えられたデフォルトの三つが通常の原因です。三つとも外側のルックアップに見えており、事後に取ったメインテーブルのダンプにはどれも見えません。

ルーティングの出力が教えてくれないこと

正しいルックアップは、カーネルがパケットを妥当な場所へ送ることを意味します。ファイアウォールが許可すること、IPsecポリシーが覆うこと、NATルールが変換すること、遠端に戻り経路があることを意味しません。それらはどれも後の段階であり、 strongSwanの転送に関する注記 が、パケットが両端で通過しなければならない連鎖を説明しています。

アプリケーションレベルのバインドも考慮しません。プロセスはインターフェースにバインドしたり、マークを設定したり、独自のリゾルバーを使って、試したものとは異なる解決をする名前で接続できます。ルックアップが正しいのに接続が失敗するとき、次の問いはどのプロセスがそれを行っているのか、そのプロセスが自分と同じテーブルを見ているのかです。

ですから診断を順序立ててください:宛先と送信元を名指しし、ルックアップを実行し、ルックアップが名指ししたテーブルとルールだけを読み、それから次の段階を試す。この順序ならルーティングの調査は数分で済み、他の人が追える記録が残るのであり、貼り付けたテーブルには決してできないことです。

関連記事