ip route show を二回実行する間に、ラボ用プリンタの /24 が消え、クライアントのログにはネットワークが変わったとだけ出ます。コマンドもプレフィックスも権限も間違っていません。ホストのルーティングモデルを所有する企業向けクライアントは、誰かが編集するたびにそのモデルを再主張するため、追加したエントリは侵入者として削除されます。同じテーブルで戦うのは負け戦です。解決策は、そのテーブルを争うのをやめ、例外を監視の目が決して届かない場所に置くことです。

監視が消えたルートを説明する

何かを再設計する前に実演してください。テーブルを読み、プレフィックスを追加し、数秒待ってからもう一度読みます。エントリがなく、削除するために何も入力していないなら、何者かが監視しています。その振る舞いを持つプロセスを見つけ、ルートが消える瞬間の前後のジャーナルを読みます。同じサービスが通常、トンネル、パケットフィルタ、リゾルバ設定を管理しているからです。ルートを残すためにそれを殺すのは、次の再接続で後悔する取引です。

ip route show
ip route add 192.168.2.0/24 dev enp0s31f6
sleep 5; ip route show

上のプレフィックスとインターフェースはプレースホルダーです。別のマシンで動く例からインターフェース名をコピーすることが、この実演が何も生まない最も一般的な理由です。

二つ目のテーブルは監視から見えない

エージェントは自分が所有するテーブルだけを再構築します。例外に専用のテーブルと、一致する宛先をそこへ送るルールを与えれば、メインテーブルは決して変わらないので、エージェントが直すものはありません。これが要点です。他人が管理するルートの名前空間と、自分だけが触る名前空間を分けるのです。

代償は保守です。二つのオブジェクトはずれる可能性があり、一覧内のルールの位置は、それが選ぶテーブル内のルートと同じくらい重要です。

例外を作り、勝たせる

テーブルを作成し、ルートをインストールし、その宛先に対してテーブルを選ぶルールを追加します。優先度は、自分のルールがクライアントの挿入したルールより前に評価されるか後に評価されるかを決め、後ろに並ぶルールには決して到達しないので、番号は飾りではなく設計の一部です。次に、カーネルが実際にどうするかを尋ねます。これは設定した内容とは別の問いです。

ip rule add to 192.168.2.0/24 table 110 pref 30010
ip route add 192.168.2.0/24 dev enp0s31f6 table 110
ip route get 192.168.2.50

ip route get は、デバイスと送信元アドレスを含め、カーネルが使うルートを解決します。テーブル識別子は出力しないので、ip rule show と組み合わせます。これは どのテーブルが勝ったかを確認するときに必要です。両者を合わせれば、唯一重要な問いに答えます。そのアドレスへの通信は意図した場所から出ているのか、という問いです。

同じ発想の別の形

宛先で考えるのをやめれば、このパターンは一般化します。トンネルがデフォルトルートを保ったまま、ローカルサブネットに到達できるようにできます。LAN接続のSSHサーバーからの応答は、トンネルに消える代わりに、届いたインターフェースから出せます。インターフェースベースのルールなら、ワイヤレスインターフェースに届くすべてをトンネルへ押し込み、ホスト自身が生成する通信はEthernetに残せます。

ip rule add iif wlan0 table 10
ip route add default dev tun0 table 10

最後のケースは宛先ではなく入力インターフェースに一致するもので、別のルール種別と別のメンタルモデルです。転送される通信には net.ipv4.ip_forward を有効にする必要もあり、遠端は送信元範囲を戻すようルーティングするか変換しなければなりません。一台のマシン上のルールが経路のもう半分を作ることは決してありません。

ルールは使い捨てとして扱う

ルールとテーブルルートはメモリ上にあります。再接続後、トンネルデバイスは名前を変え、割り当てアドレスは移動し、古い値を持つルールは黙って一致しなくなります。変更全体を所有する単一のスクリプトから再適用し、例外を信頼する前に ip rule show、現在のデバイス名、新しい ip route get を実際の宛先に対して再確認してください。

どんなに注意しても二つの境界は残ります。クライアントは依然として自身のフィルタルールとリゾルバ設定を管理しており、ルーティングの例外はどちらも上書きしません。クライアントがポリシールールも削除する場合、サポートされる道は自身のスプリットトンネルポリシーか、OpenConnectのようにルート管理を許すクライアントです。ベンダーのバイナリにパッチを当てて監視を黙らせるのは、整合性チェックが付いた保守の約束です。

テーブル番号、優先度、宛先をスクリプトの隣のメモに書いてください。そうでなければ、次の人はトンネルを上回るルールを見つけ、理由を知る術がありません。

関連記事