只是知道哪个应用程序在使用特定的端口并不足以跟踪到问题所在。有时候还需要检查传输的数据。

11.2.1 预备知识

tcpdump需要以root身份运行。你所在的系统可能默认并没有安装tcpdump。可以使用包管理器自行安装:

  1. $ sudo apt-get install tcpdump
  2. $ sudo yum install libpcap tcpdump -y
  3. $ yum install tcpdump -y

11.2.2 实战演练

tcpdumpWireshark以及其他网络嗅探程序的前端,其GUI界面支持大量的选项,我们很快就会讲到。

此处叙述并不准确。tcpdump是由Van JacobsonSally FloydVern PaxsonSteven McCanne1988年编写的。Wireshark的前身是Ethereal,是由Gerald Combs编写并于1998年发布的。尽管两者都使用了libcap来抓取网络分组,而且Wireshark可以浏览tcpdump的抓取结果,但它们属于不同的网络嗅探工具,并不是前后端的关系。详见:https://en.wikipedia.org/wiki/Tcpdumphttps://en.wikipedia.org/wiki/Wireshark以及https://wiki.wireshark.org/ libpcap。

该程序的默认行为是显示出以太网连接上的所有分组。分组显示格式如下:

  1. $ TIMESTAMP SRC_IP:PORT> DEST_IP:PORT: NAME1 VALUE1, NAME2 VALUE2,...

其中的“名称 - 值(name - value)”包括以下几个。

  • Flags:分组所具有的标志如下。
    • S 代表 SYN(发起连接)。
    • F 代表 FIN(终止连接)。
    • P代表PUSH(推送数据)。
    • R代表 RST(重置连接)。
    • 点号.表示没有对应的标志。
  • seq:指的是分组的序列号。这个序列号会回显(echoed)在ACK中来确认接收到的分组。
  • ack:作用是确认已接收到某个分组。这个值是上一个分组的序列号。

    此处关于ACK的叙述并不准确。ACK的值是期望收到对方下一个分组的第一个数据字节的序号。也就是说,如果ACK = N,则表明到序号N-1为止的所有数据都已经正确接收到。

  • win:指明了目的端的缓冲区大小。

  • options:指明了分组中定义的TCP选项。其显示形式是一系列以逗号作为分隔符的“关键字 - 值”对。

下面的输出展示了从Windows主机发往SAMBA服务器的请求,其中还掺杂DNS请求。来自不同源以及应用的各种分组混合在一起,使得很难跟踪特定的应用或主机的流量。不过tcpdump命令的一些选项能够减轻我们的负担。

  1. $ tcpdump
  2. 22:00:25.269277 IP 192.168.1.40.49182 > 192.168.1.2.microsoft-ds: Flags
  3. [P.], seq 3265172834:3265172954, ack 850195805, win 257, length 120SMB
  4. PACKET: SMBtrans2 (REQUEST)
  5. 22:00:25.269417 IP 192.168.1.44.33150 > 192.168.1.7.domain: 13394+ PTR?
  6. 2.1.168.192.in-addr.arpa. (42)
  7. 22:00:25.269917 IP 192.168.1.2.microsoft-ds > 192.168.1.40.49182: Flags
  8. [.], ack 120, win 1298, length 0
  9. 22:00:25.269927 IP 192.168.1.2.microsoft-ds > 192.168.1.40.49182: Flags
  10. P.], seq 1:105, ack 120, win 1298, length 104SMB PACKET: SMBtrans2 (REPLY)

如果不想在终端上显示tcpdump的输出,选项-w可以将输出发送到文件中。输出格式是二进制格式,可以使用选项-r读取。嗅探分组需要拥有root权限,但是显示保存在文件中的嗅探结果只用普通用户权限就可以了。
image.png
默认情况下,tcpdump会一直执行并嗅探网络分组,直到按下Ctrl-C或发送SIGTERM信号。选项-c可以限制嗅探的分组数:

  1. # tcpdump -w /tmp/tcpdump.raw -c 50
  2. tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535
  3. bytes
  4. 50 packets captured
  5. 50 packets received by filter
  6. 0 packets dropped by kernel

作为限制,我们在这里只检查单个主机或是单个应用程序的活动。

tcpdump命令行中尾部的值可以作为表达式,用于过滤分组。表达式由多个“关键字值”以及修饰符和布尔操作符组成。接下来我们将演示一些过滤器的用法。

只显示HTTP分组

关键字port可以只显示出发往或来自特定端口的分组:

  1. $ tcpdump -r /tmp/tcpdump.raw port http
  2. reading from file /tmp/tcpdump.raw, link-type EN10MB (Ethernet)
  3. 10:36:50.586005 IP 192.168.1.44.59154 > ord38s04-in-f3.1e100.net.http:
  4. Flags [.], ack 3779320903, win 431, options [nop,nop,TSval 2061350532 ecr
  5. 3014589802], length 0
  6. 10:36:50.586007 IP ord38s04-in-f3.1e100.net.http > 192.168.1.44.59152:
  7. Flags [.], ack 1, win 350, options [nop,nop,TSval 3010640112 ecr
  8. 2061270277], length 0

只显示本机生成的 HTTP 分组

如果你打算跟踪所使用的Web流量,只需要查看本机生成的HTTP分组就可以了。scr修饰符配合特定的“关键字值”就可以指定源文件中的这类分组。dst修饰符可以指定目的地址:

  1. $ tcpdump -r /tmp/tcpdump.raw port http
  2. reading from file /tmp/tcpdump.raw, link-type EN10MB (Ethernet)
  3. 10:36:50.586005 IP 192.168.1.44.59154 > ord38s04-in-f3.1e100.net.http:
  4. Flags [.], ack 3779320903, win 431, options [nop,nop,TSval 2061350532 ecr
  5. 3014589802], length 0
  6. 10:36:50.586007 IP ord38s04-in-f3.1e100.net.http > 192.168.1.44.59152:
  7. Flags [.], ack 1, win 350, options [nop,nop,TSval 3010640112 ecr
  8. 2061270277], length 0

image.png查看分组载荷(payload)以及头部

如果你想追查在网络中滥发分组的主机,只需要查看分组头部就行了。如果你打算调试Web页面或是数据库应用,你可能还得查看分组的内容。

选项-X会将分组的内容也一并输出。

关键字hose结合端口可以对发往或来自特定主机的特定端口数据进行输出限制。

and能够对两个测试条件执行逻辑与操作,使得tcpdump只输出发往或来自noucorp.comHTTP数据。下面的例子展示了一个GET请求以及服务器的回复:

  1. $ tcpdump -X -r /tmp/tcpdump.raw host noucorp.com and port http
  2. reading from file /tmp/tcpdump.raw, link-type EN10MB (Ethernet)
  3. 11:12:04.708905 IP 192.168.1.44.35652 >noucorp.com.http: Flags [P.], seq
  4. 2939551893:2939552200, ack 1031497919, win 501, options [nop,nop,TSval
  5. 2063464654 ecr 28236429], length 307
  6. 0x0000: 4500 0167 1e54 4000 4006 70a5 c0a8 012c E..g.T@.@.p....,
  7. 0x0010: 98a0 5023 8b44 0050 af36 0095 3d7b 68bf ..P#.D.P.6..={h.
  8. 0x0020: 8018 01f5 abf1 0000 0101 080a 7afd f8ce ............z...
  9. 0x0030: 01ae da8d 4745 5420 2f20 4854 5450 2f31 ....GET./.HTTP/1
  10. 0x0040: 2e31 0d0a 486f 7374 3a20 6e6f 7563 6f72 .1..Host:.noucor
  11. 0x0050: 702e 636f 6d0d 0a55 7365 722d 4167 656e p.com..User-Agen
  12. 0x0060: 743a 204d 6f7a 696c 6c61 2f35 2e30 2028 t:.Mozilla/5.0.(
  13. 0x0070: 5831 313b 204c 696e 7578 2078 3836 5f36 X11;.Linux.x86_6
  14. 0x0080: 343b 2072 763a 3435 2e30 2920 4765 636b 4;.rv:45.0).Geck
  15. 0x0090: 6f2f 3230 3130 3031 3031 2046 6972 6566 o/20100101.Firef
  16. 0x00a0: 6f78 2f34 352e 300d 0a41 6363 6570 743a ox/45.0..Accept:
  17. ...
  18. 11:12:04.731343 IP noucorp.com.http> 192.168.1.44.35652: Flags [.], seq
  19. 1:1449, ack 307, win 79, options [nop,nop,TSval 28241838 ecr 2063464654],
  20. length 1448
  21. 0x0000: 4500 05dc 0491 4000 4006 85f3 98a0 5023 E.....@.@.....P#
  22. 0x0010: c0a8 012c 0050 8b44 3d7b 68bf af36 01c8 ...,.P.D={h..6..
  23. 0x0020: 8010 004f a7b4 0000 0101 080a 01ae efae ...O............
  24. 0x0030: 7afd f8ce 4854 5450 2f31 2e31 2032 3030 z...HTTP/1.1.200
  25. 0x0040: 2044 6174 6120 666f 6c6c 6f77 730d 0a44 .Data.follows..D
  26. 0x0050: 6174 653a 2054 6875 2c20 3039 2046 6562 ate:.Thu,.09.Feb
  27. 0x0060: 2032 3031 3720 3136 3a31 323a 3034 2047 .2017.16:12:04.G
  28. 0x0070: 4d54 0d0a 5365 7276 6572 3a20 5463 6c2d MT..Server:.Tcl-
  29. 0x0080: 5765 6273 6572 7665 722f 332e 352e 3220 Webserver/3.5.2.

11.2.3 工作原理

tcpdump能够将网卡设为混杂模式,使得网卡能够接收到网络上所有的分组。这样就可以抓取到发往所在网络上其他主机的分组了。

tcpdump可用于跟踪过载网段的问题源、产生异常流量的主机、网络环路、网卡故障、恶意分组等。

利用选项-w-rtcpdump可以将分组数据以原始格式保存,允许随后以普通用户身份查看。举例来说,如果在凌晨3点出现了大量网络分组冲突,你可以设置一项cron作业,安排在凌晨3点的时候运行tcpdump,然后对比检查正常时段的网络分组。