
tcpdump是 Linux 系统提供的一个非常强大的抓包工具熟练使用它对我们排查网络问题非常有用。如果你的机器上还没有安装可以使用如下命令安装yum install tcpdump如果要使用tcpdump命令必须具有sudo权限。tcpdump常用的选项有-i指定要捕获的目标网卡名网卡名可以使用前面章节中介绍的ifconfig命令获得如果要抓所有网卡的上的包可以使用any关键字。## 抓取网卡ens33上的包 tcpdump -i ens33 ## 抓取所有网卡上的包 tcpdump -i any-X以 ASCII 和十六进制的形式输出捕获的数据包内容减去链路层的包头信息-XX以 ASCII 和十六进制的形式输出捕获的数据包内容包括链路层的包头信息。-n不要将 ip 地址显示成别名的形式-nn不要将 ip 地址和端口以别名的形式显示。-S以绝对值显示包的 ISN 号包序列号默认以上一包的偏移量显示。-vv抓包的信息详细地显示-vvv抓包的信息更详细地显示。-w将抓取的包的原始信息不解析也不输出写入文件中后跟文件名tcpdump -i any -w filename-r从利用-w选项保存的包文件中读取数据包信息。除了可以使用选项以外tcpdump还支持各种数据包过滤的表达式常见的形式如下## 仅显示经过端口 8888 上的数据包包括tcp:8888和udp:8888 tcpdump -i any port 8888 ## 仅显示经过端口是 tcp:8888 上的数据包 tcpdump -i any tcp port 8888 ## 仅显示源端口是 tcp:8888 的数据包 tcpdump -i any tcp src port 8888 ## 仅显示源端口是 tcp:8888 或目标端口是 udp:9999 的包 tcpdump -i any tcp src port 8888 or udp dst port 9999 ## 仅显示源地址是127.0.0.1 且源端口是 tcp:9999 的包 以 ASCII 和十六进制显示详细输出 ## 不显示 ip 地址和端口号的别名 tcpdump -i any src host 127.0.0.1 and tcp src port 9999 -XX -nn -vv下面我们通过三个具体的操作实例来演示一下使用tcpdump的抓包过程。实例一 连接一个正常的侦听端口假设我的服务器端的地址是127.0.0.1:12345使用 nc 命令在一个 shell 窗口创建一个服务器程序并在这个地址上进行侦听。nc –v -l 127.0.0.1 12345效果如下图所示在另外一个 shell 窗口开启 tcpdump 抓包tcpdump -i any port 12345 -XX -nn -vv效果如下然后再开一个 shell 窗口利用 nc 命令创建一个客户端去连接服务器nc -v 127.0.0.1 12345效果如下我们抓到的包如下由于我们没有在客户端和服务器之间发送任何消息其实抓到的包就是 TCP 连接的三次握手数据包分析如下三次握手过程是客户端先给服务器发送一个SYN然后服务器应答一个SYN ACK应答的序列号是递增1的表示应答哪个请求即从4004096087递增到4004096088接着客户端再应答一个ACK。这个时候我们发现发包序列号和应答序列号都变成1了这是 tcpdump 使用相对序号我们加上-S选项后就变成绝对序列号了。我们按 Ctrl C 中断 tcpdump 抓包过程并停止用 nc 开启的客户端和服务器程序然后在前面的 tcpdump 命令后面加上-S选项重新开启抓包使用命令如下tcpdump -i any port 12345 -XX -nn -vv -S然后再按顺序用 nc 命令再次启动下服务器和客户端程序。再次得到抓包结果这次得到的包的序号就是绝对序号了。实例二连接一个不存在的侦听端口实例一演示的是正常的 TCP 连接三次握手过程捕获到的数据包。假如我们连接的服务器 ip 地址存在但监听端口号不存在我们看下 tcpdump 抓包结果。除了在一个 shell 窗口启动一个 tcpdump 抓包监测在另外一个 shell 窗口用 nc 命令去连接一个不存在的侦听端口即可。 抓包数据如下这个时候客户端发送SYN服务器应答ACKRST这个应答包会导致客户端的 connect 连接失败返回。实例三连接一个很遥远的 ip或者网络繁忙的情形实际情形中还存在一种情况就是客户端访问一个很遥远的 ip或者网络繁忙服务器对客户端发送的 TCP 三次握手的网络 SYN 报文没有应答会出现什么情况呢我们通过设置防火墙规则来模拟一下这种情况。使用iptables -F先将防火墙的已有规则都清理掉然后给防火墙的 INPUT 链上增加一个规则丢弃本地网卡 lo也就是 127.0.0.1 这个回环地址上的所有 SYN 包。iptables -F iptables -I INPUT -p tcp --syn -i lo -j DROP如果读者对 CentOS 的防火墙 iptables 命令有兴趣可以使用 man iptables 在 man 手册中查看更详细的帮助。在开启 tcpdump 抓包之后和设置防火墙规则之后利用 nc 命令去连接 127.0.0.1:12345 这个地址。整个过程操作效果图如下 接着我们得到 tcpdump 抓到的数据包如下通过抓包数据我们可以看到如果连接不上一共重试了5次重试的时间间隔是 1 秒2秒4秒8秒16秒最后返回超时失败。这个重试次数在/proc/sys/net/ipv4/tcp_syn_retries内核参数中设置默认为6。TCP 四次挥手与三次握手基本上类似这里就不贴出 tcpdump 抓包的详情了强烈建议不熟悉这块的读者实际练习一遍。