「tcpdump and wireshark」-

排查 ping 延迟

问题描述

执行 ping 测试:

// ping 3 次(默认每次发送间隔1秒)
// 假设DNS服务器还是上一期配置的 114.114.114.114

# ping -c3 geektime.org
PING geektime.org (35.190.27.188) 56(84) bytes of data.
64 bytes from 35.190.27.188 (35.190.27.188): icmp_seq=1 ttl=43 time=36.8 ms
64 bytes from 35.190.27.188 (35.190.27.188): icmp_seq=2 ttl=43 time=31.1 ms
64 bytes from 35.190.27.188 (35.190.27.188): icmp_seq=3 ttl=43 time=31.2 ms

--- geektime.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 11049ms
rtt min/avg/max/mdev = 31.146/33.074/36.809/2.649 ms

在 ping 将要结束时,执行如下命令:

// 禁止接收从DNS服务器发送过来并包含googleusercontent的包

# iptables -I INPUT -p udp --sport 53 -m string --string googleusercontent --algo bm -j DROP

后三次 ping 请求都得到了响应,延迟(RTT)都是 30ms 左右。但是,汇总处三次发送和接受的总时间居然超过了 11s(11049ms)

问题原因

在三次 ping 请求中,用的都是 IP 地址,所以 DNS 解析应该没有问题。

再次执行 nsloopup 测试解析,发现能够解析,并且速度正常:

# time nslookup geektime.org
Server:    114.114.114.114
Address:  114.114.114.114#53

Non-authoritative answer:
Name:  geektime.org
Address: 35.190.27.188


real  0m0.044s
user  0m0.006s
sys  0m0.003s

我们使用 tcpdump 抓包,查看网络数据包:

# tcpdump -nn udp port 53 or host 35.190.27.188
// -nn ,表示不解析抓包中的域名(即不反向解析)、协议以及端口号
// udp port 53 ,表示只显示 UDP 协议的端口号(包括源端口和目的端口)为 53 的包
// host 35.190.27.188 ,表示只显示 IP 地址(包括源地址和目的地址)为 35.190.27.188 的包。
// 这两个过滤条件中间的“ or ”,表示或的关系,也就是说,只要满足上面两个条件中的任一个,就可以展示出来。

// 执行 ping 命令

# ping -c3 geektime.org
...
--- geektime.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 11095ms
rtt min/avg/max/mdev = 81.473/81.572/81.757/0.130 ms

// 查看 tcpdump 输出

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:02:31.100564 IP 172.16.3.4.56669 > 114.114.114.114.53: 36909+ A? geektime.org. (30)
14:02:31.507699 IP 114.114.114.114.53 > 172.16.3.4.56669: 36909 1/0/0 A 35.190.27.188 (46)
14:02:31.508164 IP 172.16.3.4 > 35.190.27.188: ICMP echo request, id 4356, seq 1, length 64
14:02:31.539667 IP 35.190.27.188 > 172.16.3.4: ICMP echo reply, id 4356, seq 1, length 64
14:02:31.539995 IP 172.16.3.4.60254 > 114.114.114.114.53: 49932+ PTR? 188.27.190.35.in-addr.arpa. (44)
14:02:36.545104 IP 172.16.3.4.60254 > 114.114.114.114.53: 49932+ PTR? 188.27.190.35.in-addr.arpa. (44)
14:02:41.551284 IP 172.16.3.4 > 35.190.27.188: ICMP echo request, id 4356, seq 2, length 64
14:02:41.582363 IP 35.190.27.188 > 172.16.3.4: ICMP echo reply, id 4356, seq 2, length 64
14:02:42.552506 IP 172.16.3.4 > 35.190.27.188: ICMP echo request, id 4356, seq 3, length 64
14:02:42.583646 IP 35.190.27.188 > 172.16.3.4: ICMP echo reply, id 4356, seq 3, length 64

// 前两行,表示 tcpdump 的选项以及接口的基本信息;从第三行开始,就是抓取到的网络包的输出。
// 这些输出的格式,都是 时间戳 协议 源地址.源端口 > 目的地址.目的端口 网络包详细信息

// 我们从这个流程中可以看到,时间最大的地方在于 PTR 反向解析
// 所以我们禁止 PTR 即可,可以参考 ping 的手册,使用 -n 选项

注意事项

这里使用 iptable 规则的原因,是为了屏蔽 PTR 记录以模拟问题:

# nslookup -type=PTR 35.190.27.188 8.8.8.8
Server:  8.8.8.8
Address:  8.8.8.8#53
Non-authoritative answer:
188.27.190.35.in-addr.arpa  name = 188.27.190.35.bc.googleusercontent.com.
Authoritative answers can be found from:

tcpdump

网络分析工具,它基于 libpcap 库,利用内核中的 AF_PACKET 套接字,抓取网络接口中传输的网络包;提供强大的过滤规则,用于从大量的网络包中,挑出最想关注的信息。

网络协议位于 RFC 文档,或者阅读 《TCP/IP 详解》 第一卷的 TCP/IP 协议族。

常用选项:
tcpdump -i eth0 // 指定过滤金额口,any 表示全部接口
tcpdump -nn // 不解析网络地址和端口号
tcpdump -c5 // 限制抓取网络包的个数
tcpdump -A // 以 ASCII 显示网络包内容
tcpdump -w file.pcap // 将抓包内容写入文件中
tcpdump -e // 输出链路层头部信息

常用表达式:
host、src host、dst host / 主机过滤 / tcpdump -nn host “ip address”
net、src net、dst net / 网络过滤 / tcpdump -nn net “192.168.0.0”
port、portrange、src port、dst port / 端口过滤 / tcpdump -nn dst port “80”
ip、ip6、arp、tcp、udp、icmp / 协议过滤 / tcpdump -nn tcp
and、or、not / 逻辑表达式 / tcpdump -nn icmp or udp
tcp[tcpflags] / 特定状态的 TCP 包 / tcpdump -nn “tcp[tcpflags] & tcp-syn != 0”

网络包的详细信息取决于协议,不同协议展示的格式也不同。所以更详细的使用方法,需要查询 tcpdump 的 man 手册

如果网络数据流量巨大,使用 tcpdump 并不直观,此时可以考虑使用 wireshark 图形化工具。

参考文献

38 | 案例篇:怎么使用 tcpdump 和 Wireshark 分析网络流量?