2024-11-08 (Fri)

Multi-homing と Policy based routing

異なるサブネットに属する 192.168.0.1/24 と 192.168.1.1/24 が割り当てられた 2 つの NIC が装着されているマシンがあり、前者のゲートウェイ 192.168.0.100 は後者のサブネット 192.168.1.0 へパケットをルーティングすることもできるし、後者のゲートウェイ 192.168.1.100 は前者のサブネット 192.168.0.0 へパケットをルーティングすることもできるという環境がある。

ここで、前者のサブネットに所属する 192.168.0.2 を持つマシンから 192.168.1.1 に対して接続しようとすると、Request Timeout エラーで接続できないという問題が生じた。いわゆる multi-homing 問題である。tcpdump 等でいろいろ調査した結果、192.168.1.1 で受け取ったパケットの返事が 192.168.0.1 を持つ NIC から送出されようとしていることが分かった。しかし、reverse path filter によってブロックされてしまうので、tcpdump でもキャプチャされない。Reverse path filter は、net.ipv4.conf.{all,interface}.rp_filter によって制御されており、フィルタを無効にすることで ping が通るようになった。ドキュメントには

The max value from conf/{all,interface}/rp_filter is usedwhen doing source validation on the {interface}.

とあり、all の設定をインターフェイスごとの個別設定が常に上書きするわけではないことに注意が必要。

しかし、192.168.0.2 から 192.168.1.1 で動いている Web サーバ(https) には依然として接続できなかった。もちろん、192.168.1.2 や 192.168.3.1 など、192.168.0.0 以外のサブネットからは問題なく接続できる。この原因は不明のままだが(ゲートウェイ上で何らかのフィルタが適用されている可能性もあるが、ゲートウェイは別の管理者のものなので設定内容は不明)、policy based routing PBRで、受け取ったのと同じ NIC から返事させることにした。

PBR では、カーネル内部に複数のルーティングテーブルを用意する。まず /etc/iproute2/rt_tables にて、ルーティングテーブルの優先順位と名前をつける。

100 eno1 # 192.168.1.1

のようなものを書き足せば良い。

そして、当マシンは NetworkManager 管理だったので、

/etc/sysconfig/network-scripts/rule-eno1

from 192.168.1.1/32 table eno1 priority 100

として、192.168.1.1 由来のパケットはこの eno1 テーブルを使うと指示した。

テーブルの中身は、 /etc/sysconfig/network-scripts/route-eno1 で定義し、

192.168.1.0/24 dev eno1 table eno1
default via 192.168.1.100 dev eno1 table eno1

とした。

設定を適用するには

sudo nmcli general reload
sudo systemctl restart NetworkManager

とする。後者だけではダメだった。

なお、試行錯誤の仮定で変なルールが定義されてしまった場合は、ip rule delete によって削除しなければならない。

読んだ

見た