一覧NW-18-1 · 通信品質と切り分け

ネットワーク障害の切り分け

一つの接続障害をDNSからHTTPまで調べます。SYNだけが続く記録とRSTが返る別試行を比較し、サーバーの記録を加えて原因を特定します。

説明

「Webへ接続できない」という症状には、名前解決、経路、近隣の解決、フィルター、待受けなど複数の原因があります。どの段階の情報かを保ちながら、同じ接続先について確認する必要があります。

一つの接続障害をDNSからHTTPまで調べます。SYNだけが続く記録とRSTが返る別試行を比較し、サーバーの記録を加えて原因を特定します。

1名前から接続先を確認

端末192.0.2.10からweb.example.test:8080へ接続できない状況です。まずAレコードが返すIPv4アドレスを調べます。

dig +short応答値を簡潔に表示 web.example.test A名前のIPv4レコード

名前解決はこの時点で198.51.100.20を返しています。DNS応答があることはTCP8080へ接続できる保証ではありません。また、OSやアプリケーション独自の名前解決とは結果が異なる場合もあります。

2パケットを渡す次ホップ

宛先IPについて端末が選ぶ経路を確認します。ここでは単一のルーティング表を使います。

ip route get選択される経路を照会 198.51.100.20接続先IP

端末は192.0.2.1へ渡し、送信元に192.0.2.10を使います。ルートが存在しても、次ホップが応答するか、その先が転送するかは別に確認します。

3次ホップのMACアドレス

経路に出たゲートウェイの近隣表を確認します。遠隔のWebサーバー自身をARPで探す構成ではありません。

ip neigh show近隣表を表示 to 192.0.2.1 dev eth0次ホップと送信インターフェース

ゲートウェイのMACが取得済みで、近隣の到達性は最近確認されています。ただしWebサーバーまでの往復やサービスの起動状態を示す結果ではありません。

4接続試行中のパケット

4秒の接続試行で採取した端末側の記録を解析します。-SでTCPシーケンス番号を絶対値表示にします。

tcpdump -n -tt -S名前解決なし・時刻と絶対seq -r timeout.pcap端末側の接続試行

同じ接続先とseq1000のSYNが0秒・1秒・3秒に出ていますが、応答はこの記録にありません。無応答だけでは、途中の破棄、相手の停止、戻り経路の問題を特定できません。

5相手側の到着と拒否ルール

同じ時間帯のサーバー側の確認記録です。宛先8080の入力ルールについて、試行前後のカウンターと待受け状態を読みます。

cat server-check.txt同時刻のルールと待受け記録

SYNの3回と同じ増加数3がdropルールに出ています。待受けもあるため、この試料ではサーバーの入力フィルターが原因です。実際の切り分けでは他の同時通信も考慮し、宛先・時刻・パケット数を対応付けます。

6拒否応答が返る場合との比較

別の試行で、待受けのない8081へ接続した記録を解析します。これは先ほどの8080とは別のポートです。

tcpdump -n -tt -STCPフラグとseq/ackを表示 -r refused.pcap別ポートへの拒否応答

SYNに対してRSTとACK1001が返ります。この試料ではTCPスタックが待受けなしを通知しています。RSTは途中の装置も生成できるため、RSTだけで生成元のプロセスまで断定しません。タイムアウトの無応答とはパケット上の差があります。

7対象ルールの修正後に再確認

管理者が8080の許可条件を修正した後、同じホスト名とポートでHTTP応答を確認します。

curl -IHEADで応答ヘッダーを取得 --connect-timeout 4接続の待ち時間 http://web.example.test:8080/元と同じ接続先

今回はHTTPの200まで返りました。DNS、経路、近隣、TCP、HTTPを順に確かめたことで、どの段階で止まったかが分かります。HEADの応答なので、Content-Lengthがあってもこの操作では本文5バイトを受け取りません。

まとめ

ルートやARPが確認できても、サービスまでの到達性は別に調べます。

無応答と拒否応答を比較し、観測できた範囲を越えて原因を断定しません。

操作履歴と解説を振り返れます。

シェル / 通信の調査

1
dig +short web.example.test A
198.51.100.20
2
ip route get 198.51.100.20
198.51.100.20 via 192.0.2.1 dev eth0 src 192.0.2.10 uid 1000
    cache
3
ip neigh show to 192.0.2.1 dev eth0
192.0.2.1 lladdr 02:00:00:00:00:01 REACHABLE
4
tcpdump -n -tt -S -r timeout.pcap
reading from file timeout.pcap, link-type EN10MB (Ethernet)
0.000000 IP 192.0.2.10.49152 > 198.51.100.20.8080: Flags [S], seq 1000, win 8192, length 0
1.000000 IP 192.0.2.10.49152 > 198.51.100.20.8080: Flags [S], seq 1000, win 8192, length 0
3.000000 IP 192.0.2.10.49152 > 198.51.100.20.8080: Flags [S], seq 1000, win 8192, length 0
5
cat server-check.txt
before: input web_tcp_8080 drop packets=12
after:  input web_tcp_8080 drop packets=15
listener: 198.51.100.20:8080 LISTEN
6
tcpdump -n -tt -S -r refused.pcap
reading from file refused.pcap, link-type EN10MB (Ethernet)
0.000000 IP 192.0.2.10.49152 > 198.51.100.20.8081: Flags [S], seq 1000, win 8192, length 0
0.020000 IP 198.51.100.20.8081 > 192.0.2.10.49152: Flags [R.], seq 0, ack 1001, win 8192, length 0
7
curl -I --connect-timeout 4 http://web.example.test:8080/
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 5
Connection: close

演習完了