tcpdump入门:分析一次完整HTTP请求(原创)

tcpdump是Linux下的截获分析网络数据包的工具,对优化系统性能有很大参考价值。

一 安装

tcpdump不是默认安装的,在CentOS下安装:

yum install tcpdump

在Ubuntu下安装:

apt-get install tcpdump

二 开始截获

tcpdump执行很简单,就直接输入即可,不过这样会截获全部的数据包,眼花缭乱,显示的内容根本没有办法用。一般都会为它加上参数,比如:

最常用的是截获某IP的主机的网络数据包:

tcpdump host 192.168.0.123

三 分析一次完整请求

为简单明了起见,我截获了一段“干净”的数据包,显示了本机对某URL发起的一次请求的全过程:

23:30:01.828266 IP 192.168.0.251.34245 > li527-105.members.linode.com.http: Flags [S], seq 2340440979, win 14600, options [mss 1460,sackOK,TS val 237397584 ecr 0,nop,wscale 7], length 0
23:30:01.931109 IP li527-105.members.linode.com.http > 192.168.0.251.34245: Flags [S.], seq 64288983, ack 2340440980, win 14480, options [mss 1440,sackOK,TS val 3220226885 ecr 237397584,nop,wscale 7], length 0
23:30:01.931221 IP 192.168.0.251.34245 > li527-105.members.linode.com.http: Flags [.], ack 1, win 115, options [nop,nop,TS val 237397594 ecr 3220226885], length 0
23:30:01.931544 IP 192.168.0.251.34245 > li527-105.members.linode.com.http: Flags [P.], seq 1:133, ack 1, win 115, options [nop,nop,TS val 237397594 ecr 3220226885], length 132
23:30:02.031923 IP li527-105.members.linode.com.http > 192.168.0.251.34245: Flags [.], ack 133, win 122, options [nop,nop,TS val 3220226987 ecr 237397594], length 0
23:30:02.032171 IP li527-105.members.linode.com.http > 192.168.0.251.34245: Flags [P.], seq 1:323, ack 133, win 122, options [nop,nop,TS val 3220226988 ecr 237397594], length 322
23:30:02.032233 IP 192.168.0.251.34245 > li527-105.members.linode.com.http: Flags [.], ack 323, win 123, options [nop,nop,TS val 237397604 ecr 3220226988], length 0
23:30:02.034852 IP 192.168.0.251.34245 > li527-105.members.linode.com.http: Flags [F.], seq 133, ack 323, win 123, options [nop,nop,TS val 237397605 ecr 3220226988], length 0
23:30:02.139101 IP li527-105.members.linode.com.http > 192.168.0.251.34245: Flags [F.], seq 323, ack 134, win 122, options [nop,nop,TS val 3220227091 ecr 237397605], length 0
23:30:02.139233 IP 192.168.0.251.34245 > li527-105.members.linode.com.http: Flags [.], ack 324, win 123, options [nop,nop,TS val 237397615 ecr 3220227091], length 0

TCP协议要建立连接要经过3次“握手”,截取的数据包也是从3次握手开始,可以看到前三个包的状态(Flags)分别是:

 [S]、[S.]、[.]

首先是客户端向服务端发送一个10位的序号给服务端;服务端收到后把它+1再返回回去;客户端检查返回来的序号是对的,就返回给服务端一个1。根据上面的描述,知道这三个包满足:第一个包的seq+1=第二个包的ack;第三个包的ack=1

连接建立了之后就是具体的数据交互了,tcpdump脚本加-X参数可以通过十六进制和ASCII方式显示出具体的数据内容,这里略过。

TCP协议要断开连接要经过4次“挥手”,上面数据包的最后3条就是挥手的过程。细心的朋友会发现前面说的4次挥手,却只有3个包,这不是笔误。

最后三个包的状态分别是:

[F.]、[F.]、[.]

首先是客户端发一个序号告诉服务器我要断开,服务器说行,服务器发回一个序号,说断开吧,客户端说:“断!”

四次挥手之所以只能看到3个数据包是因为:ACK延迟发送机制。为了提高性能,TCP在收到ACK之后会攒起来而不是立即发送的,在几种情况下才会发送:

1 超过MSS(可以理解为攒得太多了,放不下了)
2 有FIN
3 系统设置为禁用延迟(TCP_NODELAY)

倒数第二条的前面应该还有一个ACK,因为不符合上述3条,所以被延迟(一般是40ms或者200ms)了,等到倒数第二条发出时符合条件了(有FIN)就一块发出来了,所以4次挥手只能看到3个包。如果系统禁用了延迟发送,就会看到4个包了。

以上均为我自己的理解,如果理解的不对,请指正。

 评论
  可给tcpdump 加上 -S 显示原始ack序号.

  ACK固定是1, 这只是tcpdump采用相对量显示,具体数值是seq%2B1,可通过16进制察看.

  “服务器说行,服务器发回一个序号,说断开吧”这两个合并成了一个包

  三次握手第三个确认包的ack=1??不是前一个数据包得seq%2B1吗?
回复:我看到的规律第三个包得ack固定是1,不知道是不是我理解错了。
 发表评论
姓   名: