リセットパケットを投げたのは誰だ?

ネットワーク接続作業を行うと毎回のように何らかの問題が発生します。小規模なネットワーク接続であれば無視できるレベルであったり軽微な修正で済むのですが、ある程度ネットワークの規模が大きくなると問題の特定に時間を要する場合があります。

まったく疎通できないのであれば問題の機器を絞り込むことは難しくないのですが、中途半端に疎通できなかったり不意にリセットパケットが飛んできて通信が切断されるような現象が発生すると、ちょっと面倒です。pingは通るのに対向先のサーバーなどネットワーク機器にTCPコネクションが張れない、通信が突然切断された、そんな経験をしたことはありませんか?

そういった自体に遭遇したとき、トラブルの元を突き止める手段のひとつとして参考になれば幸いです。

スポンサーリンク
スポンサーリンク

パケットキャプチャで原因を探る

問題発生の状況として、サーバーへpingは通るけれどssh接続ができない状態を想定します。この場合の原因として、サーバーのポート22番が閉じている、サーバーのFW機能で弾いている、経路上のFWで弾いている、といったものが考えられます。

そこで、ping疎通に問題ないがssh接続できないときの通信をパケットキャプチャしたところ、サーバーのIPアドレスからリセットパケットが送信されている事がわかりました。pingは問題なく通ります。そこで、問題。

リセットパケットを送ったのは、誰でしょうか?次のパケットキャプチャの結果から考えてみてください。

192.168.31.128から192.168.40.129に対してping/sshを実行しています。
サーバ(192.168.40.129)からの応答パケットにマーキングしているのでマーキング箇所を注目してみてください。

さて、つぎのうち答えはどれでしょう??

  1. サーバーがリセットパケットを送信した
  2. 経路上にあるネットワーク機器(もしかしてFW)がリセットパケットを送信した

答えは次の章で。IPヘッダーの値に注目してください。答えはでましたか?

IPヘッダーはウソをつかない

どうですか?だれがリセットパケットを送信したのかすぐにわかりましたか?確信を持って即答できなければ、このまま読み進めてください。

正解は2番。「経路上にあるネットワーク機器(もしかしてFW)がリセットパケットを送信した」です。

このような状況で注目するべきは、IPヘッダーの「TTL」値です。

1. IPv4 以下の図はRFC 791からの抜粋です。この図をもとに説明します。 0 1 2 3 0 1 2 3 4 5 6 7...

TTLはIPヘッダーに含まれる8ビットの値で、ネットワーク機器を経由するごとに、ひとつずつTTL値が減ります。Tracerouteはこの仕組みを利用して通信経路を調べています。

では、実際にTTL値に注目してパケットキャプチャの結果を追いかけてみましょう。

まずキャプチャ結果2行目のTTL値に注目してください。TTL値は63です。このパケットはssh接続が切断されるとき、サーバーからリセットパケットが送信されてきたときのものです。

IP (tos 0x0, ttl  63, id 0, offset 0, flags [DF], proto: TCP (6), length: 40) 192.168.40.129.22 > 192.168.31.128.49169: R, cksum 0xcbe4 (correct), 0:0(0) ack 2098519389 win 0

次に8行目に注目してください。このときのTTL値は61です。これはサーバーからICMP応答を受信したときのものです。

IP (tos 0x0, ttl  61, id 48987, offset 0, flags [none], proto: ICMP (1), length: 60) 192.168.40.129 > 192.168.31.128: ICMP echo reply, id 1, seq 1238, length 40

おかしくありませんか?送信元IPアドレスは同じなのにどうしてTTL値が違うのでしょう?

その答えをつぎのフロー図で説明します。

TCPリセット送信フロー

このフロー図は、pingを実行したときとssh接続がリセットパケットで切断されたときの通信の流れを示しています。

pingを実行したとき、パケットはFWを通過してサーバーがping応答を送信しました。このとき、サーバーが設定した初期TTL値は64です。その後、ルーターとFWを経由してping応答が到着するとTTL値は61まで減算されました。パケットキャプチャの結果と一致しています。

これに対してsshが切断されたときはどうでしょうか?まずFWのポリシーに引っかかってFWで止められます。そしてFWはリセットパケットを送信します。偶然にもサーバーと同じくFWの初期TTL値も64でしたので、ルーターを経由してリセットパケットが送信元へ到達したときTTL値は63に減算されました。

興味深いことに、TTLの初期値はOSのTCP/IP実装に依存します。そして、カーネルパラメータをいじらない限りTTLの初期値は「64」「128」「255」のどれかである事が多いです。そのため、返って来たTTL値をみれば送信元の初期TTL値は簡単に推測できます。初期TTL値はわかっているので、逆算すればホップ数もおのずと推測できます。今回の例でいえばリセットパケットを投げたネットワーク機器(FW)の間にひとつネットワーク機器がある事がわかるはずです。

何もしていないのに切断されるとき

今回はキャプチャ結果を掲載していないのですが、アプリテストをしていると不意に通信切断が発生する事があります。このときの原因で多いのはFWやLB(ロードバランサー)がタイムアウトしてリセットパケットを飛ばした場合です。

リセットパケットで通信が切断された場合はパケットキャプチャをしていれば一発で送信元を特定できる可能性が極めて高いです。全台のパラメータ再確認をするという地道な方法も良いのですが(昔やらされました)、迅速に解決したいならばパケットキャプチャをした方が良いでしょう。

FWやLBの設定が甘いと必ず発生するので試してみてください。

最後に

顧客に「おたくのネットワーク設定ミスじゃないの?」なんて言われたら「2ホップ先にFWがありませんか?そこで弾かれている可能性があります。FWがあるならばポリシーチェックを依頼して頂けますか?」なんて即答できたら良いですね。

大変なのは、TTLで送信元を特定できる理由を説明する必要がある場合です。

以前投稿した「リセットパケットを投げたのは誰だ?」はなかなか評判が良いのですが、本当に現場で使えるの?って疑問に感じる人は少なからずいらっしゃるのではないかと思います。 遭遇した状況 クライアント端末から通信テストをすると「Pingは通る」「でもHulft...
スポンサーリンク
スポンサーリンク