この設定はアプリごとのスイッチに見えるため、人々はクライアントをWireGuardインターフェースにバインドし、そのクライアントだけがトンネルを使うと期待します。バインドが実際に行うのは送信元アドレスの選択です。その後カーネルは宛先のルートを引き、通常のデフォルトルートを見つけ、トンネルのアドレスを付けたままパケットを物理リンクから送り出します。その送信元アドレス用に選ばれたルートだけが意図を完成させます。

仕組みは、トンネルの通信だけが使うべきルーティングテーブルと、一致する送信元をそこへ送るルールの二つに分かれます。

バインドが決めるのは送信元アドレスだけ

Linuxはポリシールールがその検索を振り向ける機会を得た後、ルーティングテーブルで宛先を引いて出力インターフェースを選びます。ルールは送信元アドレス、ファイアウォールマーク、入力インターフェース、UID、さらにはポートで選択でき、どれも「すべての通信」ではなく「この通信」と言う別の方法です。VPNクライアントの設定はトンネルのルートを持つテーブルを選び、ルールはどの通信がそれを参照できるかを選びます。バインドだけではどちらも与えられません。

だからこの失敗は奇妙に見えます。アプリは確かにトンネルのアドレスを使っており、トンネルは確かに上がっており、通信は確かに間違ったインターフェースから出ています。どの文も正しく、合わせるとアドレスとルートを結びつけたものが何もない系を表しています。

トンネルに専用のテーブルを与える

wg-quickはプロファイルの指示どおりにルートを設置します。[Interface]の下にTable = 40を足すと、ルートはメインテーブルではなくテーブル40に入ります。インターフェースを上げ、ip -4 route ls table 40でトンネルのルートを、ip -4 route get 10.66.127.142でカーネルが現在その一つをどう解決するかを確認してください。ルートが専用テーブルにあれば、メインテーブルは他のすべてのために動き続けます。

広いプレフィックスを照合するのではなく、IPv6でも同じことをしてください。ip -6 rule add from fd00::2/128 lookup 40は一つのアドレスを固定し、fc00::/8はホスト上の他のインターフェースと衝突して意図より広く一致するルールを作ることがあります。

送信元ルールを追加し、カウンターを見る

次にip -4 rule add from 10.66.127.142/32 lookup 40で二つをつなぎ、同じアドレスをWireGuardインターフェースに付けたままにします。両方のルールをPostUpに入れれば、再接続時に復元されます。設定ではなく実際のリクエストで確かめると、ip route get 1.1.1.1 from 10.66.127.142がトンネルのデバイスを、curl --interface wg0 ifconfig.meが自宅のアドレスではなくトンネルのアドレスを報告するはずです。

それでも失敗するときはip -s ruleを読んでください。存在するのに一度も一致していないルールはカウンターがゼロで、これが誤ったルールとルールが無いことを区別します。この一つのコマンドで、アプリがインターフェース設定を無視したかどうかの推測が大幅に減ります。

逆の場合:SSHをトンネルの外に保つ

逆の問題も同じくらいよくあり、wg-quickがデフォルトルートを握っていて、サーバーへのSSHセッションが途中で切れます。そのルールは優先度の低い番号にあり、例外はそれより先に評価される必要があります。ip rule add dport 22 ipproto tcp table main priority 123は最近のiproute2でそれを行いますが、セレクターが使えない場合はnftablesでフローに印を付け、代わりにその印で照合してください。

戻りの経路も確認してください。接続が確立した後に沈黙するSSHセッションは通常、非対称ルーティングになっており、片方向はトンネルから、もう片方向は物理インターフェースから出ます。サーバーのアドレスに対するip route getが、応答がどちらへ向かうかを教えてくれます。

テーブル番号、送信元ルール、例外をプロファイル自体に記録してください。三つは一つの設計に属し、まとめて編集されます。

関連記事