2022年6月5日日曜日

冗長化されたルーター経由のpingが通らないことがある

 最近ハマったので記録を残しておきます。まあ例によって原因は単純なミスなんですが、例によって仰々しく書いてみます。。

図のようなネットワーク構成を想定してください。

  • 2つのネットワークがある
  • それぞれのネットワーク内にはサーバーがある
  • 2つのネットワークはルーターでつながっている
    • ルーターはVyOSを使っている
    • ルーターは2台あり、冗長化されている(片方が落ちても問題ない)

この状態でA→Bにpingを飛ばすとちゃんと返事が返ってくるのに、逆方向(B→A)は返ってこないという摩訶不思議な現象が発生していました。

補足として、firewalldやufw等のファイヤーウォールは特に入れておらず、ルーティングテーブルも適切に設定されています。

なお、これはクイズではないので、唯一の正解にたどり着く情報が与えられているわけではありません。ただし、よく読めば「ここが怪しいんじゃない?」とわかるヒントは入れてあります。

問題だった設定

各所(ネットワークインターフェース)にtcpdumpを仕込んでパケットキャプチャーしてみた結果、

  • A→B(正常)
    • 往路も復路もルーターXを通る
  • B→A(異常)
    • echo requestはAに届いており、Aからもecho replyを返している(がBに届いていない)
    • 往路はルーターXを通り、復路はルーターYを通る
    • ルーターYからBへ出るはずのパケットが出ていない

ということがわかりました。どの経路が選ばれるかは時の運であり、「なぜB→Aだけ往復の経路が違うのか?」という疑問には意味がありません。たまたま違っていただけという事実を受け入れて話を進めます。

この時点で「ルーターYの設定がおかしい」か「往路と復路で経路が違うことに問題がありそう」のどちらかが原因じゃないかということがみなさん想像ついたと思います。さらに調べたところ、原因は両方でした

VyOSには、ufwやfirewalldを使わずにファイヤーウォールを設定できる機能があり、その中でステートポリシーを設定できます。それが以下のような設定になっていました。

firewall {
  state-policy {
    invalid {
      action drop
    }
  }
}

これは本来の手順を踏まずにいきなり送りつけられたパケットを捨てる設定です。

あっ

おわかりですね。echo requestが通らずにecho replyが送りつけられる場合も「本来の手順を踏んでいない」とみなされてパケットが捨てられます。調べてないけど、いきなりTCP FINパケットが送られたときとかも捨てるのかな。

ルーターを冗長化してるんだから、echo requestとecho replyが違うルーターを通ること、つまりルーターにいきなりecho replyが通ることも当然あるわけで、この設定はアカンわけです。

解決方法

ここまでわかればほぼ終わり。2つのルーターに

firewall {
  state-policy {
    invalid {
      action accept
    }
  }
}

のようにaction acceptを設定して解決。無事双方向のpingができました。

0 件のコメント:

コメントを投稿