インフラSEの徒然ブログ

世間からすると何をしているのかよく分からないSEの仕事模様を気ままに投稿します。

【Linux】tcpdumpによるパケットの確認

サーバサイドのインフラSEに身を置いておりますと、他システムとの通信テストなどをネットワークチームと合同で対応することがよくあると思います。

 

サーバ側でFWやiptablesなどをかけていなければ、通信NGとなった場合は大体ネットワークチームが管轄するFWの設定などに問題があるので(極論)、おおよそ多くのサーバ側の人間は、ネットワークチームが設定修正するのを首をながーくして待っていることがほとんどかと思います。(私もその一人でした)

 

が、ネットワークチームに調査させといて、実はサーバ側に問題がありました。ってこともよくあります。一番しらけるパターンですね。とりあえずごめんなさいするところから始まりますが、そのあとのやり取りが多少気まずくなる場合もありますため、なるべくその状況は避けたいところ。自社の人間ならまだいいですけど、他ベンダの方とかだとまたイタイ。。

 

そうならないためにも、ネットワークチームが調査している間に、サーバ側もできる限り調査に協力することが肝要かと思います。今回は私がよく使うパケット調査ツールであるtcpdumpについて書きたいと思います。

 

tcpdumpは簡単にいうと、指定したネットワークインタフェース上を通過するパケットを目に見える形にしてくれて、どんなパケットが来ているか(来ていないのか)を確認できるツールです。下記の例ではeth0を通過するicmpパケットを拾っています。

 

 【コマンド】

tcpdump -ni eth0 icmp
ping 8.8.8.8 -c 4

 

【実行結果】

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:22:38.809758 IP 192.168.1.101 > 8.8.8.8: ICMP echo request, id 26913, seq 1, length 64
12:22:38.816623 IP 8.8.8.8 > 192.168.1.101: ICMP echo reply, id 26913, seq 1, length 64
12:22:39.810785 IP 192.168.1.101 > 8.8.8.8: ICMP echo request, id 26913, seq 2, length 64
12:22:39.817819 IP 8.8.8.8 > 192.168.1.101: ICMP echo reply, id 26913, seq 2, length 64
12:22:40.812053 IP 192.168.1.101 > 8.8.8.8: ICMP echo request, id 26913, seq 3, length 64
12:22:40.819771 IP 8.8.8.8 > 192.168.1.101: ICMP echo reply, id 26913, seq 3, length 64
12:22:41.814175 IP 192.168.1.101 > 8.8.8.8: ICMP echo request, id 26913, seq 4, length 64
12:22:41.823410 IP 8.8.8.8 > 192.168.1.101: ICMP echo reply, id 26913, seq 4, length 64

 

黄色字は自サーバ(192.168.1.101)からGoogle様のDNSサーバ(8.8.8.8)に対するpingの発信。緑字はDNSサーバからのお返事ですね。正常に応答が来ております。

GoogleDNSサーバはインターネット経由のping応答を返してくれるのです。(記事投稿時点では)そのため、サーバがインターネットに出れるかどうかの調査でよく使わせて頂いております。

 

【引数の説明】

引数 意味
n ホスト名をIPアドレスに変換させないで結果を表示させる。
i

パケットキャプチャを行うインタフェースを指定する。インタフェースが複数ある場合は指定しましょう。

確か指定しないと一番若いインタフェース(大体eth0)になったかと思います。

icmp キャプチャするプロトコルを指定します。tcpudp等も指定可能。

 

上記の例は通信がうまくっている場合なので、NGだった場合も見てみましょう。

 

 【コマンド】

tcpdump -ni eth0 icmp
ping 192.168.2.1 -c 4

 

【実行結果】

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:39:04.982117 IP 192.168.1.101 > 192.168.2.1: ICMP echo request, id 27209, seq 1, length 64
12:39:05.981727 IP 192.168.1.101 > 192.168.2.1: ICMP echo request, id 27209, seq 2, length 64
12:39:06.981840 IP 192.168.1.101 > 192.168.2.1: ICMP echo request, id 27209, seq 3, length 64
12:39:07.981527 IP 192.168.1.101 > 192.168.2.1: ICMP echo request, id 27209, seq 4, length 64

 

自サーバから送り続けるだけで、応答がありません。途中の経路上のFWなどで遮断されているか、サーバ側で遮断しているか、ルーティングが間違っているか、そもそも対向のサーバが存在しないか。理由は色々あるかと思いますが、少なくとも自サーバからeth0のインタフェース経由でpingを送信している事までは分かります。

そんなのdump取らずとも分かるじゃないか、と思われがちですが、これが意外とサーバからすると重要で、サーバ側のルーティングを正しく切っていないことが原因で、本来使ってはいけないインタフェースからpingを送出していることもあります。本来eth1からping送信しなくてはいけないのに、デフォゲのeth0から出てる、とかですね。そういった切り分けにも使えたりします。

 

お次はポート指定。私もよく使います。

 

 【コマンド】

tcpdump -nni eth0 port 20 or port 21

  

この状態でクライアントからFTP接続をしようとしてみます。今回オプションのnを2つ付けていますが、これによりポート番号もサービス名に変換されなくなります。また、FTP通信では管理通信として21番ポート、データ通信として20番ポートを使用するので、キャプチャ対象をorで2つ指定しています。

 

【実行結果】

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
19:36:41.972720 IP 192.168.1.100.63501 > 192.168.1.101.21: Flags [S], seq 3908844646, win 8192, options [mss 1460,nop,wscale 0,nop,nop,sackOK], length 0
19:36:41.972756 IP 192.168.1.101.21 > 192.168.1.100.63501: Flags [S.], seq 2821952715, ack 3908844647, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
19:36:41.973075 IP 192.168.1.100.63501 > 192.168.1.101.21: Flags [.], ack 1, win 8192, length 0
19:36:41.974361 IP 192.168.1.101.21 > 192.168.1.100.63501: Flags [P.], seq 1:21, ack 1, win 229, length 20: FTP: 220 (vsFTPd 3.0.2)
19:36:41.982247 IP 192.168.1.100.63501 > 192.168.1.101.21: Flags [P.], seq 1:15, ack 21, win 8172, length 14: FTP: OPTS UTF8 ON
19:36:41.982302 IP 192.168.1.101.21 > 192.168.1.100.63501: Flags [.], ack 15, win 229, length 0
19:36:41.982384 IP 192.168.1.101.21 > 192.168.1.100.63501: Flags [P.], seq 21:47, ack 15, win 229, length 26: FTP: 200 Always in UTF8 mode.
19:36:42.022859 IP 192.168.1.100.63501 > 192.168.1.101.21: Flags [.], ack 47, win 8146, length 0

 

分かりやすく色づけしていますが、黄色字の部分は有名な3ウェイハンドシェイクかと思われます。(違ってたらすみません。)緑字部分は[FTP]の文字列も見えますし、アプリケーション層のパケットのやり取りですね。たぶん。この状態はクライアントからFTP接続を要求し、サーバ側はクライアントに対してFTPのログインユーザの入力を待ち受けている状態です。ではクライアント側でログインユーザを入力してみます。今回は事前に作成したftpuserというユーザでログインしてみます。

 

【実行結果】

19:45:26.944612 IP 192.168.1.100.63678 > 192.168.1.101.21: Flags [P.], seq 15:29, ack 47, win 8146, length 14: FTP: USER ftpuser
19:45:26.944757 IP 192.168.1.101.21 > 192.168.1.100.63678: Flags [P.], seq 47:81, ack 29, win 229, length 34: FTP: 331 Please specify the password.
19:45:26.984862 IP 192.168.1.100.63678 > 192.168.1.101.21: Flags [.], ack 81, win 8112, length 0

 

こんなん出ました。黄色字にしましたが、[ftpuser]と出ています。tcpdumpでパケットをキャプチャしますと、クライアント側で入力したユーザ名も確認できます。緑字のところにもありますが、今サーバはクライアントに対して、ftpuserのパスワード入力を待ち受けている状態です。早速パスワードも入力します。

 

【実行結果】

19:59:19.487178 IP 192.168.1.100.63810 > 192.168.1.101.21: Flags [P.], seq 29:44, ack 81, win 8112, length 15: FTP: PASS Password
19:59:19.510261 IP 192.168.1.101.21 > 192.168.1.100.63810: Flags [P.], seq 81:104, ack 44, win 229, length 23: FTP: 230 Login successful.
19:59:19.551253 IP 192.168.1.100.63810 > 192.168.1.101.21: Flags [.], ack 104, win 8089, length 0

 

ログインできました。そしてdump結果にクライアント側で入力したパスワードが表示されています。今回ftpuserのパスワードはPasswordと設定していましたが、dumpを取るとそのまま表示されるんですね。FTPは特に暗号化しないアプリケーションなので、当然といえば当然ですが。ログインにも成功しています。

 

次に、FTPログインしたクライアント側でlsコマンドを叩いてみます。

 

【実行結果】

20:00:23.982151 IP 192.168.1.100.63810 > 192.168.1.101.21: Flags [P.], seq 77:104, ack 218, win 7975, length 27: FTP: PORT 192,168,1,100,249,68
20:00:23.982316 IP 192.168.1.101.21 > 192.168.1.100.63810: Flags [P.], seq 218:269, ack 104, win 229, length 51: FTP: 200 PORT command successful. Consider using PASV.
20:00:23.989049 IP 192.168.1.100.63810 > 192.168.1.101.21: Flags [P.], seq 104:110, ack 269, win 7924, length 6: FTP: NLST
20:00:23.989259 IP 192.168.1.101.20 > 192.168.1.100.63812: Flags [S], seq 734891644, win 29200, options [mss 1460,sackOK,TS val 500462092 ecr 0,nop,wscale 7], length 0
20:00:23.989489 IP 192.168.1.100.63812 > 192.168.1.101.20: Flags [S.], seq 201576010, ack 734891645, win 65535, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
20:00:23.989528 IP 192.168.1.101.20 > 192.168.1.100.63812: Flags [.], ack 1, win 229, length 0
20:00:23.989570 IP 192.168.1.101.21 > 192.168.1.100.63810: Flags [P.], seq 269:308, ack 110, win 229, length 39: FTP: 150 Here comes the directory listing.
20:00:23.989595 IP 192.168.1.101.20 > 192.168.1.100.63812: Flags [P.], seq 1:11, ack 1, win 229, length 10
20:00:23.989606 IP 192.168.1.101.20 > 192.168.1.100.63812: Flags [F.], seq 11, ack 1, win 229, length 0
20:00:23.989708 IP 192.168.1.100.63812 > 192.168.1.101.20: Flags [.], ack 12, win 8212, length 0
20:00:23.989781 IP 192.168.1.101.21 > 192.168.1.100.63810: Flags [P.], seq 308:332, ack 110, win 229, length 24: FTP: 226 Directory send OK.
20:00:23.989880 IP 192.168.1.100.63810 > 192.168.1.101.21: Flags [.], ack 332, win 7861, length 0
20:00:23.995457 IP 192.168.1.100.63812 > 192.168.1.101.20: Flags [F.], seq 1, ack 12, win 8212, length 0
20:00:23.995519 IP 192.168.1.101.20 > 192.168.1.100.63812: Flags [.], ack 2, win 229, length 0

 

lsコマンドを叩きますと、ユーザログイン先のカレントディレクトリに存在するディレクトリ一覧が表示されます。黄色字のところにありますが、正常にディレクトリ一覧を入手できているようです。クライアント側でもディレクトリ一覧が確認できました。

が、ここで注目してほしいのは、緑字のポート番号のところです。今までずっと21番ポートだけを使ってやり取りをしていたのですが、今回20番ポートが登場してきました。これは、lsコマンドでディレクトリ一覧を参照すると、20番ポートでデータのやり取りが行われるからです。

FTPでサーバにログインはできるのだけど、データ転送ができない、といった事象がよーーくあります。いろいろな原因が考えられますが、FTPがアクティブモードで起動していて21番ポートはFWで許可されているけどデータ転送ポートは許可されていないってのがほとんど。この辺のこともtcpdumpを使えば見えてきます。

 

このように、tcpdumpを使えばサーバ-クライアント間の通信がよーく見えてきます。クライアントからサーバへ通信を行っているのに、サーバ側のtcpdumpの結果にパケットが乗ってこなければ、経路上のどこかでパケットが破棄されていることが分かりますし、サーバ上でパケットは確認できるけども、アプリケーションが正常に動作していなければ、サーバ側に問題があると考えられます。問題発生時の切り分け手段として、是非使ってみてください。