ゲートウェイ経由で公開したサービスは、インターネットの大半からは動作し、ある一つのオフィスからだけ失敗する。誰かがトンネルを確認し、リクエストが届くのを見て、応答も同じ経路で戻るはずだと結論づける。Linuxはそういう動作をせず、トンネルをどれだけ調べても応答は変わらない。応答は宛先によってルーティングされ、失敗しているその一つの呼び出し元は、ホストがすでに直接到達できるサブネット上にある。

外向きパケットを実際に決めるもの

カーネルはパケットの宛先に対する経路を検索し、ポリシールールを優先順位の順に参照したうえで、一致したルールが選ぶテーブルを参照する。パケットが到着したインターフェースは、それを意味のあるものにするルールやマークが書かれていない限り、何の役割も果たさない。これはこのホストのルーティングに関する事実であり、トンネルの不具合ではない。

したがって、トンネルで受け取ったリクエストが、物理インターフェースから出ていく応答を生み、どの機器もエラーを報告しないまま通信が片方向になることがある。トンネルについて結論を出す前に、両方向を確認すること。誤った方向へ出た応答はトンネルのカウンターから消えるため、何かが送られたかどうかで両端の見解が食い違う。ルールに触れる前に、どのカウンターが動いたかを確認すること。

ローカルサブネットが勝つ理由

ローカルネットワーク上にアドレスを持つホストは、メインテーブルにそのプレフィックスへの接続経路を持ち、接続経路は直接一致する。呼び出し元が同じサブネットから来る場合、検索はトンネルを検討する前にローカルリンクを見つける。

この非対称性が診断を紛らわしくする。より広いインターネットからの呼び出し元はローカル経路に一致しないため動作するが、オフィスのプレフィックスを共有する唯一の呼び出し元は失敗する、そして誰かがテストに使うのはまさにその呼び出し元である。

ピアのカバレッジはインストール済み経路とは同じではない

トンネル側では、ピアの許可範囲がトンネルに送ってよいものと、そこから受け入れる送信元を記述する。ローカルのルーティングテーブルがパケットをどこへ送るかについては何も語らない。

トンネルツールがホストにデフォルトルートをインストールすると、無関係なトラフィックを巻き添えとしてトンネルに引き込むことがある。代わりにポリシールールが判断を持つべき場面では、ツールのルートインストールオプションはまさにそれを防ぐために存在し、アドレス、鍵、エンドポイント設定はそのまま維持される。利便性のために追加されたデフォルトルートは、ホストが自身のローカルネットワークを失うよくある原因である。

送信元アドレスでテーブルを選ぶ

送信元ベースのルールは、サービスアドレスからの応答を、デフォルトがトンネルである専用テーブルへ送り、それ以外はすべてメインテーブルを使い続ける。ローカルで使われていないテーブル番号と優先度番号を選び、何かを挿入する前に既存のルールを読むこと。保存されたファイルではなく稼働中のルールを読むこと、再起動後には両者が異なることがあるからだ。

ip -6 route add default dev wg0 table 200
ip -6 rule add priority 32000 from 2001:db8:aa::20/128 lookup 200
ip -6 rule add priority 32001 from 2001:db8:aa::20/128 unreachable

最後の行は、経路がない場合にローカルリンクへフォールバックするのではなく、目に見える形で失敗させる。送信元は本当にホストに割り当てられている必要があり、通常のローカル検索とメイン検索は以前の位置に残らなければならない。ルールは送信元でテーブルを選ぶのであって、テーブル間でプレフィックス長を比較するのではない。

経路を確認し、それからサービスを確認する

キャプチャから推測するのではなく、サービスアドレスを送信元セレクターとしてカーネルに何をするかを尋ねること。ここで正しい答えを得られれば、パケットトレースを丸ごと節約できる。

ip -6 route get 2001:db8:bb::30 from 2001:db8:aa::20

出力にはトンネル名が示されるはずだ。次に、触れていない送信元を試し、それが依然としてローカルリンクを使うことを確認して、変更が一つのアドレスに限定されたことを確かめる。より広いセレクターでは、元の不具合について何も証明できない。

これで直らないもの

ゲートウェイの転送、ファイアウォールルール、ICMPv6の動作はそのままにしておくこと、送信元ルートはそのどれも置き換えないからだ。Packet Too Bigメッセージが欠けていれば、どのテーブルが検索に勝ったとしても大きな応答は壊れたままである。ルーティングルールを追加する前にそれを直さないと、症状は変更後も残る。

これを適用する前に公開モデルを確認すること。独自のバックエンド接続を開くリバースプロキシは自身の送信元を示し、呼び出し元を保持しないため、その設計ではこの不具合は起こりえない。そこにルールを適用すると、何も解決せず本当の原因を隠すルーティング例外を追加することになる。

最後に、ルール番号とテーブルをホストの構成管理に書き込むこと。手作業で追加したポリシールールは次の再構築で消え、オフィスの呼び出し元は同じ苦情を抱えて戻ってくる。

関連記事