conf t

インフラエンジニアのメモ

行きと帰りのルーティングが違うときに通信ができない

f:id:monaski:20151030221324j:plain 以前自宅環境構築中に別セグメントにつながらない事象があったときのメモ。

192.168.1.0/24セグメントを生活セグメントとして使用しております。
192.168.2.0/24セグメントが検証用セグメントです。

R1はプロバイダーから支給されているルータです。
ここにR2ルータを接続し、セグメントを分けています。

問題

なぜか、生活セグメントのPC1から検証セグメントのPC2(webサーバ)が表示できません。
pingは通ります。
PC2へのsshも通りません。

PC1のデフォルトゲートウェイDNSサーバの設定は、R1ルータになっています。
R1ルータには、192.168.1.2セグメントへのスタティックルートの設定を確かに実施しました。

pingは通るのにweb表示とsshができないのはおかしい。
PC2のファイアウォールの設定の問題かな?とPC2を調べるも、特に問題点は見つからず。

原因

原因は、通信の行きと帰りの経路が違うことに起因しています。
詳しく見ていきましょう。

PC1からPC2へ通信する際、行きの経路は以下になります。

①PC1はPC2の場所がわからないため、デフォルトゲートウェイであるR1へパケットを送信する
②R1はPC2が192.168.2.0/24にあると知っているため、PC2へパケットを送信する

一方帰りは以下の経路になります。
①PC2はPC1を知らないため、デフォルトゲートウェイであるR2へパケットを送信する
②R2はPC1と同じセグメントにあり、PC1を知っているため、PC1にパケットを送信する

行きはR1を経由しているにもかかわらず、帰りはR1を経由せず直接PC1へと通信がなされているのです。

f:id:monaski:20151030221530j:plain

行きと帰りの経路が違うことは、L3レベルでは問題ないことと思いますが(実際pingは通っています)、
さらに上位層のチェックが入る場合には、通信が成立しないことがあるようです。

PC1にてパケットキャプチャしてPC1からPC2へのHTTP通信を調査すると、
最初の3wayハンドシェイクは成功しているように見えるものの、
その後PC2からハンドシェイク後もPC2からSYN,ACKがPC1宛に跳び続けております。

どうやら、PC1からPC2へのACKが届いていないようです。
以下3wayハンドシェイクでいうと③が届いておりません。

①PC1⇒PC2へSYN
②PC2⇒PC1へSYN,ACK
③PC1⇒PC2へACK

そのため、PC2が②を再送し続けているようです。

PC1でのパケットキャプチャを再度確認しましたが、③のACKは確かに送信されています。
ということは、通信経路上でドロップしていることになります。
PC2上でパケットキャプチャすると、③は来ていません。
怪しいのはR1かR2です。
そこでR2はL3スイッチのなのでミラーポートを設定し、そこでパケットキャプチャしました。
結果、③のACKが届いておりませんでした。
よってパケットはR1でドロップされております。
R1はプロバイダから配布されるルータのため、詳細なログが確認できず、ドロップされたログ の確認はできませんでした。

R1でパケットがドロップされるのは、以下の理由ではないかと推測いたします。
R1からPC1⇒PC2の通信を見ると、①のSYNは通過しますが、②のSYN,ACKはR1を通過しません。(行きと帰りが違うため)
そのため、③のACKがR1に来た際に、まだ②が来ていないのに③が来るのはおかしいと判断し、R1がパケットをドロップしているのではないでしょうか。

解決方法

PC1のデフォルトゲートウェイをR2にするか、もしくはPC1に192.168.2.0/24へのネクストホップをR2に設定したところ解消しました。
後者の場合は行きと帰りの経路が同じになるから解決できるのはわかるのですが、
前者の場合、デフォルトゲートウェイをR2にしたら、今度はインターネットに接続するときに同じ問題が発生すると思ったのですが、
R2(L3スイッチ)は行きと帰りの経路が異なってもパケットをドロップしないようです。
実際にR2でパケットキャプチャしたところ、行きの通信しか通過していないようなのですが、PC1からインターネットへの通信は
問題なく可能でした。

おまけ:ICMPリダイレクトについて

PC1にてパケットキャプチャした際に、R1からPC1へ、ICMPリダイレクトを送信しておりました。

ICMPリダイレクトとは、送信元のホストに、自分より近い経路がある際に、送信元に教えてあげる機能とのこと。
ICMPリダイレクトを受け取った送信元は、次回から通知された宛先へゲートウェイを変えるらしい。

R1がICMPリダイレクトでPC1に、R2のほうがPC2に近いことを教えてくれていたようだ。
このICMPリダイレクトによってPC1は次からは直接R2にパケットを送信するらしい。

しかし、R1からのICMPリダイレクトは、PC1からのpingの度に発信されており、PC1の宛先もR1のまま変わっている気配がない。
ルーティングテーブルを確認してみても、PC1のルーティングテーブルは更新されていない。
ICMPリダイレクトが効いていないんじゃないのだろうか?

調べてみると、案の定WindowsではICMPリダイレクトを受け付けていないらしい。

ICMP redirects - Windows Forum - Spiceworks

WindowsファイアウォールにICMPリダイレクトの設定個所を発見したが、グレーアウトされており、 管理者権限でも変更することができなかった。