在Linux中使用TCPDUMP命令进行数据包捕获

时间:2020-03-21 11:46:30  来源:igfitidea点击:

在本教程中,我们将研究Linux系统管理员工具箱中一个非常知名的工具。
在故障排除过程中,有时会证明此工具非常有用。
借助此工具,我们可以在数据包到达应用程序堆栈之前对其进行分析。
有时会检测到服务器为什么不响应ping请求,应用程序为什么不响应特定计算机等。

它除了TCPDUMP之外没有其他工具。
Tcpdump是一种非常强大的工具,因为它可以根据给定的不同参数捕获数据包。
它在网络层上运行,因此能够捕获进出计算机的所有数据包。
我们可以使用tcpdump捕获数据包并将其保存到文件中,以供日后分析。

TCPDUMP使用Libpcap(用于数据包捕获的c/C++库)。

还有其他工具可以像wireshark一样完成数据包捕获/分析的工作,但是tcpdump可以使所有捕获保持原始状态。
这意味着它向我们显示了它捕获的原始数据。

  • tcpdump在网络层中工作
  • 网络数据包头由发送者,目的地,状态信息和其他标志信息组成。
  • 默认情况下,TCPDUMP仅捕获数据包中的前96字节数据。

可以从这里下载TCPDUMP

如今,大多数Linux发行版都预装了tcpdump工具。
但是我们需要具有root或者sudo权限才能运行该工具。

[root@myvm ~]# rpm -qa | grep tcpdump
tcpdump-3.9.4-15.el5

上面的命令搜索rpm数据库并查找tcpdump软件包。

与其他数据包分析器相比,使用TCPDUMP的优点是我们将需要详细了解TCP中的某种协议。
否则,如果不了解TCP协议,解密tcpdump捕获的原始数据将非常困难。

因此,以某种方式使用TCPDUMP将使我们随时了解特定协议如何通过网络进行通信。

让我们看一下TCPDUMP中可用的一些基本选项,然后再讨论其他选项。

此选项用于指定接口。
使用此选项,我们可以告诉tcpdump捕获进入特定接口的数据包。
例如

[root@myvm ~]# tcpdump -i lo
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes

从上面的命令可以明显看出,tcpdump仅在回送接口上侦听数据包。
并且如前所述,输出清楚地表明其仅捕获了96个字节的数据包。

[root@myvm ~]# tcpdump -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

上面的命令将转储所有发往eth0接口的数据包。
TCPDUMP输出将非常快,如果我们有很多连接,它将填满整个屏幕。

如果我们不将tcpdump与-n方法一起使用,则所有发件人和目标主机地址都将采用“名称”格式,这意味着所有ip都将显示为主机名。

将-n选项与tcpdump一起使用将禁用名称查找。
这将以发件人和收件人的IP地址格式显示所有输出。

通过使用-c选项,我们可以指定需要捕获的数据包数量。
例如,如果我们只想捕获2个数据包,则将执行如下所示的操作。

[root@myvm ~]# tcpdump -n -c 2 -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
01:55:55.393805 IP 172.16.140.41.5910 > 172.16.134.85.51907: . 31288437:31292817(4380) ack 3681524545 win 71
01:55:55.394626 IP 172.16.134.85.51907 > 172.16.140.41.5910: . ack 2920 win 1053
2 packets captured
4 packets received by filter
0 packets dropped by kernel

如以上命令及其结果所示,我们可以清楚地看到,我们告诉tcpdump仅使用-c选项从eth0接口捕获2个数据包。

如前所述,默认情况下,tcpdump仅捕获数据包的第96个字节。
但是,假设我们需要捕获其完整大小的数据包,那么我们需要将size选项-s与它的参数一起传递。

我们可以使用-s0选项捕获整个数据包,也可以使用带有-s参数的字节数。

[root@myvm ~]# tcpdump -s0 -n -c 2 -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
01:58:31.011304 IP 172.16.134.85.51907 > 172.16.140.41.5910: P 3681527491:3681527497(6) ack 32290881 win 776
01:58:31.011312 IP 172.16.140.41.5910 > 172.16.134.85.51907: . ack 6 win 71
2 packets captured
2 packets received by filter
0 packets dropped by kernel

从上面的输出中可以看到,它清楚地提到捕获大小为65535字节而不是96字节(捕获大小在上述命令的输出中为粗体)

从我们到目前为止看到的所有上述输出中,该输出仅向我们显示了有关发送者和接收者ip地址的信息。
假设我们想要发送者和接收者的mac地址,则可以包含-e选项。

请参阅下面的示例输出。

[root@myvm ~]# tcpdump -s0 -e -n -c 2 -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
02:00:10.545520 1a:e5:ad:00:b5:20 > Broadcast, ethertype IPv4 (0x0800), length 92: 172.16.140.20.netbios-ns > 172.16.140.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
02:00:10.546598 00:15:17:8d:0c:9c > 46:0a:98:3d:41:b1, ethertype IPv4 (0x0800), length 210: 172.16.140.41.56153 > 172.16.140.33.49155: P 1489870205:1489870349(144) ack 2064846002 win 96 <nop,nop,timestamp 1157179149 382990921>
2 packets captured
4 packets received by filter
0 packets dropped by kernel

从上面显示的输出中可以看到输出中的MAC地址(Mac地址在输出中以粗体显示)

如果希望tcpdumpt输出向我们显示更多详细信息,如显示所有标志和tcp中的标头,则可以使用详细选项。

-v表示更多的信息包信息,-vv表示更多信息,-vvv选项表示更多信息。
输出示例如下所示

[root@myvm ~]# tcpdump -s0 -vvv -e -n -c 2 -i eth0
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
02:02:21.671828 00:15:17:83:0c:9c > 00:23:47:4c:97:00, ethertype IPv4 (0x0800), length 4434: (tos 0x0, ttl  64, id 20588, offset 0, flags [DF], proto: TCP (6), length: 4420) 172.16.140.41.5910 > 172.16.134.85.51907: ., cksum 0x7bd6 (incorrect (-> 0x2515), 34181155:34185535(4380) ack 3681533777 win 71
02:02:21.672181 00:23:47:4c:97:00 > 00:15:17:83:0c:9c, ethertype IPv4 (0x0800), length 338: (tos 0x10, ttl  59, id 34117, offset 0, flags [DF], proto: TCP (6), length: 324) 172.17.4.111.ssh > 172.16.140.41.58728: P, cksum 0x4294 (correct), 4107752623:4107752895(272) ack 2150369028 win 33148 <nop,nop,timestamp 2658690172 1157308260>
2 packets captured
3 packets received by filter
0 packets dropped by kernel

tcpdump中的此选项可用于显示绝对序列号。
现在什么是序号?

序列号在TCP中使用,以标识已发送或者已接收的数据包数量。
每当计算机启动TCP连接时,它都会在三向握手过程中将其序列号通知另一端。

借助序列号,接收方和发送方开始知道已传输了多少数据。

TCPDUMP甚至显示这些序列号。
使用-S选项将显示绝对tcp序列号,而不是与先前数据包相关的序列号。

使用-w选项,我们可以捕获输出并将所有输出保存到指定文件。
以后可以在诸如editcap之类的工具的帮助下对该文件进行分析。

建议对文件名使用.pcap扩展名,因为这会使其他数据包分析器可读。

[root@myvm ~]#  tcpdump -w sampletcpdump.pcap -s0 -vvv -e -n -c 2 -i eth0
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
2 packets captured
5 packets received by filter
0 packets dropped by kernel

不要用thorugh cat或者vim打开文件来读取文件...因为我们将无法读取它。

为了读取我们刚刚捕获的文件,我们需要在tcpdump命令中使用-r选项,并将filename作为命令的参数传递。

[root@myvm ~]# tcpdump -r sampletcpdump.pcap
reading from file sampletcpdump.pcap, link-type EN10MB (Ethernet)
02:04:04.712709 IP 172.16.134.150.50438 > m1-sv-xbox2.5919: P 1245960226:1245960232(6) ack 671383339 win 64701
02:04:04.712724 IP myvm.5919 > 172.16.134.150.50438: . ack 6 win 46

到现在为止,在上面显示的所有示例中,我们都将所有数据包都发送到所有端口,并且这些数据包来自随机协议,无论捕获过程中使用的工具如何,它都可以显示这些内容。

现在,以防万一,如果我们要捕获到达一台服务器的端口22的数据包。

[root@myvm ~]# tcpdump -s0 -vvv -e -n -c 2 -i eth0 port 22
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
02:09:33.185445 00:23:47:4c:97:00 > 00:15:17:83:0c:9c, ethertype IPv4 (0x0800), length 338: (tos 0x10, ttl  59, id 5386, offset 0, flags [DF], proto: TCP (6), length: 324) 172.16.0.111.ssh > 172.16.140.41.58728: P, cksum 0xacee (correct), 4107814047:4107814319(272) ack 2150369076 win 33148 <nop,nop,timestamp 2659121792 1157739776>
02:09:33.185453 00:15:17:83:0c:9c > 00:23:47:4c:97:00, ethertype IPv4 (0x0800), length 66: (tos 0x10, ttl  64, id 46661, offset 0, flags [DF], proto: TCP (6), length: 52) 172.16.140.41.58728 > 172.16.0.111.ssh: ., cksum 0x49c9 (correct), 1:1(0) ack 272 win 501 <nop,nop,timestamp 1157741788 2659121792>
2 packets captured
2 packets received by filter
0 packets dropped by kernel

从上面的输出中可以清楚地看到,使用port 22选项捕获的所有数据包均用于ssh。

如果要忽略进入端口80的数据包并显示所有其余数据包,则可以使用相同的端口选项,但以不同的方式来实现。

让我们看一个使用tcpdump做到这一点的例子

[root@myvm ~]# tcpdump -i eth0 -n -c 5 'port !80'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
02:11:30.822544 arp who-has 192.168.0.152 (Broadcast) tell 192.168.0.152
02:11:30.875907 IP 172.16.140.41.5910 > 172.16.134.85.51907: . 44976382:44982222(5840) ack 3681551939 win 71
02:11:30.876707 IP 172.16.134.85.51907 > 172.16.140.41.5910: . ack 2920 win 1791
02:11:30.876724 IP 172.16.140.41.5910 > 172.16.134.85.51907: . 5840:8760(2920) ack 1 win 71
02:11:30.877604 IP 172.16.134.85.51907 > 172.16.140.41.5910: . ack 5840 win 1780
5 packets captured
6 packets received by filter
0 packets dropped by kernel

通过执行上述操作,遗嘱屏幕将被丢弃,其中包含除朝向端口80的流量以外的所有流量。

显示针对特定主机的数据包

假设我们在拍摄某些内容时遇到麻烦,并且只对了解去往或者来自特定主机的流量感兴趣。
在这种情况下,我们可以通过以下命令要求tcpdump仅显示该主机的数据包。

[root@theitroad ~]# tcpdump -i eth0 -c 5 host 192.168.159.128

主机选项可以用来做到这一点。
始终使用-c选项指定没有要捕获的数据包是一个好主意,否则,屏幕将与所有捕获的数据包一起转储。

使用tcpdump显示来自源的数据包

现在,我们甚至可以只要求显示具有特定源地址的数据包就可以走得更远。
这可以通过以下命令来完成。

[root@theitroad ~]# tcpdump -i eth0 -c 5 src host 192.168.159.128

因此,我们只需要将“ src”选项与主机选项放在一起即可,如上所示。

同样,我们可以为目的地进行操作,如下所示。

[root@theitroad ~]# tcpdump -i eth0 -c 5 dst host 192.168.159.128

使用tcpdump命令过滤协议

我们可以借助tcpdump轻松获取有关某种协议的数据包的信息。
如果不使用相关选项和参数过滤tcpdump输出,则目标数据包可能会丢失在tcpdump转储的大量输出中。

让我们看看如何查看其中包含某些协议的数据包。
这样做非常简单,我们只需要在命令后传递协议名称作为参数即可。

[root @ theitroad~] tcpdump -i eth0 icmp

或者

[root @ theitroad~] tcpdump -i eth0 tcp

或者

[root @ theitroad~] tcpdump -i eth0 udp

或者

[root @ theitroad~] tcpdump -i eth0 arp

使用以下选项和格式,我们可以轻松匹配特定Mac地址的icmp流量。
我们可以使用一些可以与该命令一起使用的有趣的运算符来进一步过滤tcpdump的输出。

  • &&或者“ and”
  • ||或者“or”

让我们看看如何在tcpdump中使用这些选项。

[root@theitroad ~]# tcpdump -i eth0 '((icmp) and ((ether dst host 00:0C:29:93:A0:52)))'

上面的命令将仅显示目标MAC地址00:0C:29:93:A0:52的icmp流量。