排查 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 分析网络流量?