Linux下的抓包工具Tcpdump(linux 抓包 tcpdump)
suiw9 2024-11-17 01:40 25 浏览 0 评论
tcpdump 就是根据使用者的定义对网络上的数据包进行截获的包分析工具。tcpdump 可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供 and、or、not 等逻辑语句来帮助你去掉无用的信息。
Linux下的抓包工具Tcpdump
1. 基本语法
主要介绍一下使用 tcpdump 工具时经常会使用到的参数!
过滤表达式可以给 tcpdump 传送过滤表达式来起到网络包过滤的作用,而且可以支持传入单个或多个过滤表达式。当你传入的过滤表达式含有 shell 通配符时,别忘使用单引号把表达式括起来,以防 shell 自作主张的把含有通配符的表达式先进行了解释和通配。我们可以使用 man pcap-filter 命令来查看帮助信息,你会发现,过滤表达式大体可以分成三种过滤条件,类型、方向和协议,这三种条件的搭配组合就构成。
[1] 过滤主机
- 抓取所有经过 eth1,目的或源地址是 192.168.1.1 的网络数据tcpdump -i eth1 host 192.168.1.1
- 指定源地址tcpdump -i eth1 src host 192.168.1.1
- 指定目的地址tcpdump -i eth1 dst host 192.168.1.1
[2] 过滤端口
- 抓取所有经过 eth1,目的或源端口是 25 的网络数据tcpdump -i eth1 port 25
- 指定源端口tcpdump -i eth1 src port 25
- 指定目的端口tcpdump -i eth1 dst port 25
# 只查目标机器端口是53或80的网络包
dst port 53
dst port 53
# tcpdump还支持如下的类型
host:指定主机名或IP地址
例如host roclinux.cn或host 202.112.18.34
net :指定网络段
例如arp net 128.3或dst net 128.3
portrange:指定端口区域
例如src or dst portrange 6000-6008
如果我们没有设置过滤类型,那么默认是host
# tcpdump -i eth0 -c 3 'dst port 53 or dst port 53'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:29:04.530130 IP 114.255.192.96.29832 > 116.255.245.206.http: Flags [S], seq 3169042560, win 5840, options [mss 1460,sackOK,TS val 2949111416 ecr 0], length 0
13:29:04.530660 IP 116.255.245.206.43211 > ns.sc.cninfo.net.domain: 40188+ PTR? 206.245.255.116.in-addr.arpa. (46)
13:29:04.548589 IP 114.255.192.96.29832 > 116.255.245.206.http: Flags [.], ack 3709396068, win 5840, options [nop,nop,TS val 2949111475 ecr 1601243970], length 0
3 packets captured
10 packets received by filter
0 packets dropped by kernel
[3] 网络过滤
- tcpdump -i eth1 net 192.168
- tcpdump -i eth1 src net 192.168
- tcpdump -i eth1 dst net 192.168
# 想查看这个源机器和那个目的机器之间的网络包
设置src-source和dst-destination就好了,tcpdump还支持使用and和or来进行搭配组合呢!
如果没有设置的话,默认是src or dst。
# tcpdump -i eth0 'dst 8.8.8.8'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:21:23.281978 IP 116.255.245.206 > google-public-dns-a.google.com: ICMP echo request, id 23081, seq 1, length 64
13:21:24.286663 IP 116.255.245.206 > google-public-dns-a.google.com: ICMP echo request, id 23081, seq 2, length 64
13:21:25.288612 IP 116.255.245.206 > google-public-dns-a.google.com: ICMP echo request, id 23081, seq 3, length 64
^C
3 packets captured
5 packets received by filter
0 packets dropped by kernel
[4] 协议过滤
- tcpdump -i eth1 arp
- tcpdump -i eth1 ip
- tcpdump -i eth1 tcp
- tcpdump -i eth1 udp
- tcpdump -i eth1 icmp
# 只想抓UDP的包,不被TCP的包打扰
可以把udp改为ether、ip、ip6、arp、tcp、rarp等等
# 为啥这些协议里没有应用层协议呢?
其实理由很简单,应用层协议非基础类网络协议,经常会新增或淘汰。
tcpdump不会深入到应用层部分去智能解析,所以你看到的tcpdump支持的protocol都是应用层以下的。
# tcpdump -i eth0 -c 10 'udp'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
11:25:20.801612 IP 116.255.245.48.54808 > 229.111.112.12.csd-mgmt-port: UDP, length 4
11:25:20.802120 IP 116.255.245.206.54313 > ns.sc.cninfo.net.domain: 5256+ PTR? 12.112.111.229.in-addr.arpa. (45)
11:25:21.145126 IP ns.sc.cninfo.net.domain > 116.255.245.206.54313: 5256 NXDomain 0/0/0 (45)
11:25:21.145315 IP 116.255.245.206.46658 > ns.sc.cninfo.net.domain: 15551+ PTR? 48.245.255.116.in-addr.arpa. (45)
11:25:21.153966 IP 116.255.245.43.62220 > 229.111.112.12.csd-mgmt-port: UDP, length 4
11:25:21.180135 IP 116.255.245.61.hsrp > all-routers.mcast.net.hsrp: HSRPv0-hello 20: state=active group=21 addr=116.255.245.33
11:25:21.231151 IP ns.sc.cninfo.net.domain > 116.255.245.206.46658: 15551 NXDomain 0/0/0 (45)
7 packets captured
8 packets received by filter
0 packets dropped by kernel
[5] 常用表达式
- 非
- ! or not
- 且
- && or and
- 或
- || or or
- 抓取所有经过 eth1,目的地址是 192.168.1.254 或 192.168.1.200 端口是 80 的 TCP 数据
- tcpdump -i eth1 '((tcp) and (port 80) and ((dst host 192.168.1.254) or (dst host 192.168.1.200)))'
- 抓取所有经过 eth1,目标 MAC 地址是 00:01:02:03:04:05 的 ICMP 数据
- tcpdump -i eth1 '((icmp) and ((ether dst host 00:01:02:03:04:05)))'
- 抓取所有经过 eth1,目的网络是 192.168,但目的主机不是 192.168.1.200 的 TCP 数据
- tcpdump -i eth1 '((tcp) and ((dst net 192.168) and (not dst host 192.168.1.200)))'
# tcpdump -i eth0 -nn -X 'port 53' -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
19:48:33.285838 IP 116.255.245.206.47940 > 8.8.8.8.53: 22768+ A? www.baidu.com. (31)
0x0000: 4500 003b c341 0000 4011 3c93 74ff f5ce E..;.A..@.<.t...
0x0010: 0808 0808 bb44 0035 0027 b457 58f0 0100 .....D.5.'.WX...
0x0020: 0001 0000 0000 0000 0377 7777 0562 6169 .........www.bai
0x0030: 6475 0363 6f6d 0000 0100 01 du.com.....
1 packets captured
1 packets received by filter
0 packets dropped by kernel
2. 协议包头
介绍常见的,协议的包头定义格式!
- IP 数据报格式
Linux下的抓包工具Tcpdump
- 以太网帧格式
Linux下的抓包工具Tcpdump
- TCP 头格式
Linux下的抓包工具Tcpdump
- UDP 头格式
Linux下的抓包工具Tcpdump
- HTTP 协议格式
Linux下的抓包工具Tcpdump
Linux下的抓包工具Tcpdump
3. 包头过滤
主要介绍 TCP 和 UDP 协议包头的各个字段的对应含义以及抓取方式!
首先了解如何从包头过滤信息
proto[x:y] : 过滤从x字节开始的y字节数。比如ip[2:2]过滤出3、4字节(第一字节从0开始排)
proto[x:y] & z = 0 : proto[x:y]和z的与操作为0
proto[x:y] & z !=0 : proto[x:y]和z的与操作不为0
proto[x:y] & z = z : proto[x:y]和z的与操作为z
proto[x:y] = z : proto[x:y]等于z
操作符 : >, <, >=, <=, =, !=
IP头 ==> 只针对IPv4
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding | <-- optional
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DATA ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IP选项设置了吗?
- 一般的IP头是20 字节,但 IP 头有选项设置,不能直接从偏移 21 字节处读取数据。IP 头有个长度字段可以知道头长度是否大于 20 字节。
+-+-+-+-+-+-+-+-+
|Version| IHL |
+-+-+-+-+-+-+-+-+
- 通常第一个字节的二进制值是:01000101,分成两个部分
- 0100 = 4 表示 IP 版本, 0101 = 5 表示 IP 头 32 bit 的块数4 x 5 = 20 bytes5 x 32 bits = 160 bits160 bits / 2 = 20 bytes
- 如果第一字节第二部分的值大于 5,那么表示头有IP 选项,下面介绍两种过滤方法
方法一 ==> 比较法
# 比较第一字节的值是否大于`01000101`,这可以判断IPv4带IP选项的数据和IPv6的数据。
# `01000101`十进制等于`69`,计算方法如下所示
# 如果设置了IP选项,那么第一字节是01000110(十进制70)
# 过滤规则:`tcpdump -i eth1 'ip[0] > 69'`,IPv6的数据也会匹配
0 : 0 \
1 : 2^6 = 64 \ 第一部分 (IP版本)
0 : 0 /
0 : 0 /
-
0 : 0 \
1 : 2^2 = 4 \ 第二部分 (头长度)
0 : 0 /
1 : 2^0 = 1 /
64 + 4 + 1 = 69
方法二 ==> 位操作
# 正确的过滤方法
# (1)tcpdump -i eth1 'ip[0] & 15 > 5'
# (2)tcpdump -i eth1 'ip[0] & 0x0f > 5'
0100 0101 : 第一字节的二进制
0000 1111 : 与操作
<=========
0000 0101 : 结果
分片标记
- 当发送端的MTU大于到目的路径链路上的MTU时就会被分片,权威的请参考《TCP/IP 详解》
- Fragment Offset字段只有在分片的时候才使用
- 要抓Flags中带DF位标记的不分片的包,第七字节的值应该是:01000000 = 64
- tcpdump -i eth1 'ip[6] = 64',从0开始编号
分片信息在IP头的第七和第八字节
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Bit 0: 保留,必须是0
Bit 1: (DF) 0 = 可能分片, 1 = 不分片
Bit 2: (MF) 0 = 最后的分片, 1 = 还有分片
抓分片包
- 匹配MF分片包,第七字节的值应该是:00100000 = 32tcpdump -i eth1 'ip[6] = 32'
- 最后分片包的开始 3 位是 0,但是有Fragment Offset字段
- 匹配分片和最后分片tcpdump -i eth1 '((ip[6:2] > 0) and (not ip[6] = 64))'
- 测试分片可以用如下命令ping -M want -s 3000 192.168.1.1
匹配小 TTL
- TTL字段在第九字节,并且正好是完整的一个字节,TTL 最大值是255,二进制为11111111。可以用下面的命令验证一下ping -M want -s 3000 -t 256 192.168.1.200ping: ttl 256 out of range在网关可以用下面的命令看看网络中谁在使用traceroutetcpdump -i eth1 'ip[8] < 5'
+-+-+-+-+-+-+-+-+
| Time to Live |
+-+-+-+-+-+-+-+-+
抓大于 X 字节的包
- 大于 600 字节tcpdump -i eth1 'ip[2:2] > 600'
更多的 IP 过滤
首先还是需要知道 TCP 基本结构,再次推荐《TCP/IP 详解》,卷一就够看的了
- TCP 头
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |C|E|U|A|P|R|S|F| |
| Offset| Res. |W|C|R|C|S|S|Y|I| Window |
| | |R|E|G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 抓取源端口大于 1024 的 TCP 数据包
- tcpdump -i eth1 'tcp[0:2] > 1024'
- 匹配TCP数据包的特殊标记
TCP标记定义在TCP头的第十四个字节
+-+-+-+-+-+-+-+-+
|C|E|U|A|P|R|S|F|
|W|C|R|C|S|S|Y|I|
|R|E|G|K|H|T|N|N|
+-+-+-+-+-+-+-+-+
- TCP 三次握手
源发送SYN
目标回答SYN, ACK
源发送ACK
没女朋友的童鞋要学习一下:
1. MM,你的手有空吗?--
2. 有空,你呢?\~~
3. 我也有空 *_*
失败的loser是酱紫的:
1. MM,这是你掉的板砖吗?(SYN)  ̄▽ ̄
2. 不是,找拍啊?(RST-ACK) ˋ﹏ˊ
- 只抓 SYN 包,第十四字节是二进制的 00000010,也就是十进制的 2
- tcpdump -i eth1 'tcp[13] = 2'
- 抓 SYN, ACK (00010010 or 18)
- tcpdump -i eth1 'tcp[13] = 18'
- 抓 SYN 或者 SYN-ACK
- tcpdump -i eth1 'tcp[13] & 2 = 2'
- 用到了位操作,就是不管 ACK 位是啥。
- 抓 PSH-ACK
- tcpdump -i eth1 'tcp[13] = 24'
- 抓所有包含 FIN 标记的包(FIN 通常和 ACK 一起,表示幽会完了,回见)
- tcpdump -i eth1 'tcp[13] & 1 = 1'
- 抓 RST(勾搭没成功,伟大的 greatwall 对她认为有敏感信息的连接发 RST 包,典型的棒打鸳鸯)
- tcpdump -i eth1 'tcp[13] & 4 = 4'
TCP 各种状态的标记
Linux下的抓包工具Tcpdump
补充知识
- 这里提供了部分常用的字段偏移名字
- icmptype (ICMP 类型字段)
- icmpcode (ICMP 符号字段)
- tcpflags (TCP 标记字段)
- ICMP类型值有:
- icmp-echoreply
- icmp-unreach
- icmp-sourcequench
- icmp-redirect
- icmp-echo
- icmp-routeradvert
- icmp-routersolicit
- icmp-timxceed
- icmp-paramprob
- icmp-tstamp
- icmp-tstampreply
- icmp-ireq
- icmp-ireqreply
- icmp-maskreq
- icmp-maskreply
- TCP标记值
- tcp-fin
- tcp-syn
- tcp-rst
- tcp-push
- tcp-push
- tcp-ack
- tcp-urg
- 按照 TCP 标记位抓包
- 只抓 SYN 包tcpdump -i eth1 'tcp[tcpflags] = tcp-syn'
- 抓 SYN, ACKtcpdump -i eth1 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0'
- 抓 SMTP 数据
- tcpdump -i eth1 '((port 25) and (tcp[(tcp[12]>>2):4] = 0x4d41494c))'
- 抓取数据区开始为”MAIL”的包,”MAIL”的十六进制为 0x4d41494c。
- 抓 HTTP GET 数据
- tcpdump -i eth1 'tcp[(tcp[12]>>2):4] = 0x47455420'
- “GET “的十六进制是 47455420
- 抓 SSH 返回
- tcpdump -i eth1 'tcp[(tcp[12]>>2):4] = 0x5353482D'
- “SSH-“的十六进制是 0x5353482D
- 抓老版本的 SSH 返回信息,如”SSH-1.99..”
- tcpdump -i eth1 '(tcp[(tcp[12]>>2):4] = 0x5353482D) and (tcp[((tcp[12]>>2)+4):2] = 0x312E)'
4. 详细注解
分析对应协议头部的对应位置展示!
如果是为了查看数据内容,建议用**tcpdump -s 0 -w filename**把数据包都保存下来,然后用wireshark的Follow TCP Stream/Follow UDP Stream来查看整个会话的内容。
-s 0是抓取完整数据包,否则默认只抓 68 字节。另外,用tcpflow也可以方便的获取TCP 会话内容,支持tcpdump的各种表达式。
UDP 头
- 抓 DNS 请求数据tcpdump -i eth1 udp dst port 53
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| Source | Destination |
| Port | Port |
+--------+--------+--------+--------+
| | |
| Length | Checksum |
+--------+--------+--------+--------+
| |
| DATA ... |
+-----------------------------------+
其他选项
-c参数对于运维人员来说也比较常用,因为流量比较大的服务器,靠人工CTRL+C还是抓的太多,甚至导致服务器宕机,于是可以用-c参数指定抓多少个包。
- 上面的命令计算抓 10000 个 SYN 包花费多少时间,可以判断访问量大概是多少time tcpdump -nn -i eth0 'tcp[tcpflags] = tcp-syn' -c 10000 > /dev/null
5. 常用选项
详细介绍几乎所有 Tcpdump 工具的使用参数和功能特点!
- 【-i选项】- 指明网卡设备是interface的含义,是指我们有义务告诉tcpdump希望他去监听哪一个网卡。这个选项,在我们一台服务器有多块网卡时很有必要。
- 【-nn选项】- 端口不转换意思是说当tcpdump遇到协议号或端口号时,不要将这些号码转换成对应的协议名称或端口名称。比如,众所周知21端口是FTP端口,我们希望显示 21,而非tcpdump自作聪明的将它显示成FTP。
- 【-X选项】- 显示原始数据告诉tcpdump命令,需要把协议头和包内容都原原本本的显示出来。(tcpdump 会以16进制和ASCII的形式显示),这在进行协议分析时是绝对的利器。
- 【-c选项】- 抓取数据数量是count的含义,这设置了我们希望tcpdump帮我们抓几个包。设置的是 1,所以tcpdump不会帮我再多抓那怕一个包回来。
- 【-t选项】- 输出时不打印时间戳
# tcpdump -i eth0 -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:37:21.843233 IP 172.16.242.168.37490 > 180.97.33.108.https: Flags [.], ack 689150289, win 16616, length 0
1 packets captured
466 packets received by filter
435 packets dropped by kernel
# tcpdump -i eth0 -c 1 -t
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
IP 172.16.242.168.49653 > 172.16.242.2.domain: 13085+ A? safebrowsing.google.com. (41)
1 packets captured
144 packets received by filter
113 packets dropped by kernel
- 【-v选项】- 输出更详细的信息加了-v选项之后,在原有输出的基础之上,你还会看到tos值、ttl值、id值、len总长度、checknum校验值等。
# tcpdump -i eth0 -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:39:37.165046 IP 172.16.242.168.52751 > 117.34.37.33.https: Flags [P.], seq 442060690:442060731, ack 2316077603, win 17688, length 41
1 packets captured
151 packets received by filter
120 packets dropped by kernel
# tcpdump -i eth0 -c 1 -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:40:13.260016 IP (tos 0x0, ttl 64, id 9853, offset 0, flags [DF], proto TCP (6), length 40)
172.16.242.168.37502 > 180.97.33.108.https: Flags [.], cksum 0x4fca (correct), ack 156783245, win 16616, length 0
1 packets captured
6 packets received by filter
0 packets dropped by kernel
- 【-F选项】- 指定过滤表达式所在的文件还记得我们在第一招中所提到的命令么,我帮助大家回忆一下:tcpdump -i eth0 -nn -X 'port 53' -c 1这里面的'port 53'便叫做过滤表达式,用于设置我们抓包的条件的,只有满足过滤条件的网络包,才会被抓过来。当这个过滤条件非常复杂,或者我们需要将一个过滤条件固化下来复用的时候,就会想到把它存到一个文本文件中。此时,-F选项就会派上用场。我们建立了一个filter.txt文本文件来存储过滤表达式,然后通过-F来指定filter.txt,这样tcpdump就会心知肚明地读取filter.txt中的内容作为过滤条件。
# cat filter.txt
port 53
# tcpdump -i eth0 -c 1 -t -F filter.txt
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
IP 116.255.245.206.54357 > ns.sc.cninfo.net.domain: 36720+ A? www.baidu.com. (31)
1 packets captured
6 packets received by filter
0 packets dropped by kernel
- 【-w选项】- 将流量保存到文件中通过下面的例子可以看到,通过-w选项将流量都存储在了flowdata文件中了。大家是否有兴趣less下flowdata,看看里面都是什么东东?悲剧,原来都是二进制格式的,无法直接通过文本方式查看。tcpdump的-w方式是把raw packets(原始网络包)直接存储到文件中了,也就是存储的都是结构体形式,而非是分析之后的文本格式的信息,因此大家是无法直接通过less命令查看的。那么,怎么查看呢?大家想必也想到了,就是用-r选项。
# tcpdump -i eth0 -w flowdata
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
^C327 packets captured
327 packets received by filter
0 packets dropped by kernel
# less flowdata
"flowdata" may be a binary file. See it anyway?
- 【-r选项】- 读取 raw packets 文件其实上面的命令就是在不知不觉中进行了流量回放,你会发现网络包被抓的速度都按照历史进行了回放,真像一个时光机 !由于是按raw packets来存储的,所以你完全可以使用-e、-l和过滤表达式来对输出信息进行控制,十分方便。
# tcpdump -r flowdata
reading from file flowdata, link-type EN10MB (Ethernet)
10:45:23.455758 IP 172.16.242.168.40058 > 117.34.37.32.https: Flags [P.], seq 2287886069:2287886114, ack 956870133, win 65535, length 45
10:45:23.456117 IP 117.34.37.32.https > 172.16.242.168.40058: Flags [.], ack 45, win 64240, length 0
10:45:23.456565 IP 172.16.242.168.40058 > 117.34.37.32.https: Flags [P.], seq 45:76, ack 1, win 65535, length 31
10:45:23.456721 IP 117.34.37.32.https > 172.16.242.168.40058: Flags [.], ack 76, win 64240, length 0
10:45:23.456900 IP 172.16.242.168.40058 > 117.34.37.32.https: Flags [F.], seq 76, ack 1, win 65535, length 0
10:45:23.457045 IP 117.34.37.32.https > 172.16.242.168.40058: Flags [.], ack 77, win 64239, length 0
10:45:23.467109 IP 117.34.37.32.https > 172.16.242.168.40058: Flags [FP.], seq 1, ack 77, win 64239, length 0
10:45:23.467143 IP 172.16.242.168.40058 > 117.34.37.32.https: Flags [.], ack 2, win 52724, length 0
10:45:26.407157 IP 172.16.242.168.48750 > 172.16.242.2.domain: 14588+ A? www.baidu.com. (31)
10:45:26.407495 IP 172.16.242.168.48750 > 172.16.242.2.domain: 60890+ AAAA? www.baidu.com. (31)
10:45:26.408853 IP 172.16.242.168.46443 > 172.16.242.2.domain: 21719+ A? www.baidu.com. (31)
10:45:26.411392 IP 172.16.242.168.52147 > 172.16.242.2.domain: 55202+ A? ss1.bdstatic.com. (34)
10:45:26.411578 IP 172.16.242.168.52147 > 172.16.242.2.domain: 65317+ AAAA? ss1.bdstatic.com. (34)
10:45:26.417304 IP 172.16.242.2.domain > 172.16.242.168.48750: 60890 1/1/0 CNAME www.a.shifen.com. (115)
- 【-e选项】- 增加以太网帧头部信息输出在刚才加-e选项的输出中,会发现有oui Unknown的字样,这oui是什么东东呢?OUI,即Organizationally unique identifier,是组织唯一标识符。在任何一块网卡(NIC)中烧录的6字节MAC地址中,前 3 个字节体现了 OUI,其表明了 NIC 的制造组织。通常情况下,该标识符是唯一的。
# tcpdump -i eth0 -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:20:51.886750 IP 172.16.242.168.46570 > 172.16.242.2.domain: 603+ A? wiki.centos.org. (33)
# tcpdump -i eth0 -c 1 -e
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
10:21:10.790558 00:0c:29:4a:40:c3 (oui Unknown) > 00:50:56:f7:3f:ff (oui Unknown), ethertype IPv4 (0x0800), length 1095: 172.16.242.168.37312 > 180.97.33.108.https: Flags [P.], seq 2109242280:2109243321, ack 2118171162, win 63000, length 1041
- 如果还是看不懂,说明你忘记了以太网协议的头格式,我再这里补充下,帮大家回忆回忆。
cpp
struct sniff_ethernet {
/* 目的主机的地址 */
u_char ether_dhost[ETHER_ADDR_LEN];
/* 源主机的地址 */
u_char ether_shost[ETHER_ADDR_LEN];
/* IP? ARP? RARP? etc */
u_short ether_type;
};
- 【-l选项】- 使得输出变为行缓冲选项-l的作用就是将tcpdump的输出变为行缓冲方式,这样可以确保tcpdump遇到的内容一旦是换行符即将缓冲的内容输出到标准输出,以便于利用管道或重定向方式来进行后续处理。众所周知,Linux/UNIX的标准I/O提供了全缓冲、行缓冲和无缓冲三种缓冲方式。标准错误是不带缓冲的,终端设备常为行缓冲,而其他情况默认都是全缓冲的。大家在使用tcpdump时,有时会有这样的需求:对于 tcpdump 输出的内容,提取每一行的第一个域,即时间域,并输出出来,为后续统计所用,这种场景下,我们就需要使用到-l来将默认的全缓冲变为行缓冲了。如果不加-l选项,那么只有全缓冲区满,才会输出一次,这样不仅会导致输出是间隔不顺畅的,而且当你ctrl-c时,很可能会断到一行的半截,损坏统计数据的完整性。
# tcpdump -i eth0 -l |awk '{print $1}'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
22:56:57.571680
22:56:57.572103
22:56:57.599515
22:56:57.706286
22:56:57.888108
22:56:57.888296
22:56:57.973546
22:56:57.973768
22:56:57.975660
22:56:58.019052
22:56:58.019318
^C146 packets captured
161 packets received by filter
0 packets dropped by kernel
6. 实例演示
展示一下使用的使用方式,以备即时即用!
这个 ftp、ftp-data 到底对应哪个端口?除了 ftp/ftp-data,还有哪些服务名称我可以直接用呢?在 Linux 系统中,/etc/services 这个文件里面,就存储着所有知名服务和传输层端口的对应关系。这个对应关系是由 IANA 组织(互联网数字分配机构)来全权负责的,你可以到这个链接互联网数字分配机构通过 Web 方式查到。如果你直接把/etc/services 里的 ftp 对应的端口值从 21 改为了 8888,那么 tcpdump 就会去抓端口含有 8888 的网络包了。
# 抓取通过eth0网卡且来源是wsescape.com服务器
tcpdump -i eth0 'host wsescape.com'
# 抓取通过eth0网卡且wsescape.com和baidu.com和google.com之间通讯的网络包
tcpdump -i eth0 'host wsescape.com and (baidu.com or google.com)'
# 抓取使用ftp端口和ftp数据端口的网络包
tcpdump 'port ftp or ftp-data'
# 抓取wsescape.com和baidu.com之间建立TCP三次握手中第一个网络包
# 即带有SYN标记位的网络包,另外,目的主机不能是qiyi.com
tcpdump 'tcp[tcpflags] & tcp-syn != 0 and not dst host qiyi.com'
# 打印IP包长超过576字节的网络包
tcpdump 'ip[2:2] > 576'
# 打印广播包或多播包,同时数据链路层不是通过以太网媒介进行的
tcpdump 'ether[0] & 1 = 0 and ip[16] >= 224'
- ip[0] & 0xf0 != 5
- IP 协议的第 0-4 位表示 IP 版本号,可以是 IPv4(值为 0100)或者 IPv6(0110)。IP 协议的第 5-8 位表示首部长度,单位是 4 字节,如果首部长度为默认的 20 字节(4 * 5)的话,此值应为 5,即 0101。ip[0]则是取这两个域的合体。0xf 中的 0x 表示十六进制,f0 是十六进制数,转换成 8 位的二进制数是 0000 1111。而 5 是一个十进制数,它转换成 8 位二进制数为 0000 0101。有了上面这些分析很清楚的知道,语句中!=的左侧部分就是提取 IP 包首部长度域,如果首部长度不等于 5,就满足过滤条件。言下之意也就是说,要求 IP 包的首部中含有可选字段。
- ip[0] & 0x0f == 4
- 经过上述的例子很清楚的知道,这样例子是想判断 IP 版本号是否为 IPv4。大家可能已经有所体会,在写过滤表达式时,你需要把协议格式完全背在脑子里,才能把表达式写对。可这对大多数人来说,可能有些困难。为了让 tcpdump 工具更人性化一些,有一些常用的偏移量,可以通过一些名称来代替。比如 icmptype 表示 ICMP 协议的类型域、icmpcode 表示 ICMP 的 code 域,tcpflags 则表示 TCP 协议的标志字段域。如果一个过滤表达式有多个过滤条件,那么就需要使用逻辑符了,其中,!或 not 都可以表示否定,&&与 and 都可以表示与,而||与 or 都可以表示或。
# 分析下面这三个语句来加深记忆
tcpdump 'tcp[tcpflags] & tcp-syn != 0 and not dst host qiyi.com'
tcpdump 'ip[2:2] > 576'
tcpdump 'ether[0] & 1 = 0 and ip[16] >= 224'
7. 独门秘籍
独门秘籍,非你莫属!
- 使用-A 选项,则 tcpdump 只会显示 ASCII 形式的数据包内容,不会再以十六进制形式显示
- 使用-XX 选项,则 tcpdump 会从以太网部分就开始显示网络包内容,而不是仅从网络层协议开始显示
- 使用-D 选项,则 tcpdump 会列出所有可以选择的抓包对象
# tcpdump -D
1.eth0
2.any (Pseudo-device that captures on all interfaces)
3.lo
- 如果想查看哪些 ICMP 包中“目标不可达、主机不可达”的包,请使用这样的过滤表达式 icmp[0:2]==0x0301
- 要提取 TCP 协议的 SYN、ACK、FIN 标识字段,请使用这样的过滤表达式
# SYN
tcp[tcpflags] & tcp-syn
# ACK
tcp[tcpflags] & tcp-ack
# FIN
tcp[tcpflags] & tcp-fin
- 要提取 TCP 协议里的 SYN-ACK 数据包,不但可以使用上面的方法,也可以直接使用最本质的方法 tcp[13]==18
- 如果要抓取一个区间内的端口,可以使用 portrange 语法:tcpdump -i eth0 -nn 'portrange 52-55' -c 1 -XX
8. 输出分析
分析 Tcpdump 到底输入了些什么内容!
- 现在,我们对于开头抓取的包进行彻底的剖析,来深入理解其内容。
# tcpdump -i eth0 -nn -X 'port 53' -c 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
19:48:33.285838 IP 116.255.245.206.47940 > 8.8.8.8.53: 22768+ A? www.baidu.com. (31)
0x0000: 4500 003b c341 0000 4011 3c93 74ff f5ce E..;.A..@.<.t...
0x0010: 0808 0808 bb44 0035 0027 b457 58f0 0100 .....D.5.'.WX...
0x0020: 0001 0000 0000 0000 0377 7777 0562 6169 .........www.bai
0x0030: 6475 0363 6f6d 0000 0100 01 du.com.....
1 packets captured
1 packets received by filter
0 packets dropped by kernel
- 【第 1 行】这一行,简单易懂,就是说你的命令里没有用到-v 和-vv,如果希望看到更全的输出内容,可以使用这两个选项。如果你有兴趣,可以试试,看看加上-vv 后,到底输出内容里会多些什么。
- 【第 2 行】这一句表示我们监听的是通过 eth0 这个 NIC 设备的网络包,且它的链路层是基于以太网的,要抓的包大小限制是 65535 字节。包大小限制值可以通过-s 选项来设置,如果你要追求高性能,建议把这个值调低,这样可以有效避免在大流量情况下的丢包现象。
- 【第 3 行】19:48:33.285838 => 分别对应着这个包被抓到的时、分、秒、微妙IP => 表示这个包在网络层是 IP 包116.255.245.206.47940 => 表示这个包的源 IP 为 116.255.245.206,源端口为 47940。> => 这个大于号表示数据包的传输方向8.8.8.8.53 => 表示这个包要发向的目的端 IP 是 8.8.8.8,目标端口为 53,也就是我们熟知的 DNS 服务端口22768+ A? www.baidu.com. (31) => 这是 DNS 协议的内容,即请求 www.baidu.com 的 A 纪录
- 【第 4/5/6/7 行】接下来便是 IP 包的内容了,是除去了以太网之后剩下的内容,其中左侧部分是十六进制内容,右侧部分是相应的 ASCII 码内容。
–
- IP 协议的首部分析
0x0000: 4500 003b c341 0000 4011 3c93 74ff f5ce E..;.A..@.<.t...
0x0010: 0808 0808 bb44 0035 0027 b457 58f0 0100 .....D.5.'.WX...
0x0020: 0001 0000 0000 0000 0377 7777 0562 6169 .........www.bai
0x0030: 6475 0363 6f6d 0000 0100 01 du.com.....
最外层是 IP 数据包,最开始的 1 字节(8bit)中,前 4bit 表示 IP 的版本,此处为 4,表示这是一个 IPv4 版本的 IP 包
后 4bit 表示这 IP 包的首部长度,此处的数字是 5,由于单位是 4 字节,因此可以计算得出这个 IP 包的首部长度是固定的 20 字节
0x bite
45 ==> 0100 0101
在 IP 版本和首部长度之后,接下来的 1 字节(8bit)是 00
这是 IP 协议的服务类型域(TOS),由于已经很少使用,因此此处被置为 00
0x bite
00 ==> 0000 0000
后面的 2 字节(16bit)是 003b,表示整个 IP 包的总长度(首部长度+数据长度),单位是字节
因此可以知道这个 IP 包的总长度是 59 字节(0x3b 需要转换为十进制)
0x 十进制
003b ==> 59
再向下的 2 字节(16bit)是标识域
如果 IP 包的大小超过了数据链路层的 MTU 限制,就需要对 IP 包进行分拆,此时就要用这个域来表示哪些包在分拆前是同一组的
此处的标识域值为 0xc341
0x 十进制
c341 ==> 49985
再继续向向下看,便是 3bit 的标志位
最高位为保留位,中间一位为 DF(don’t fragment),最低位为 MF(more fragments)
可以看到这三位是用来控制 IP 拆包后的组装所用,由于此包没有拆包,因此这三位都被置为 0
0x bite
'0' ==> 000
与上面的标志位配合的是紧接着的 13bit 的片偏移,但由于本包没有拆包,因此此域也无用,因此为 0
0x bite
000 ==> 0 0000 0000 0000
紧接着是 8bit 的 TTL(Time To Live,即生存周期),此包的值为 0x40,换算成十进制是 64
这表明这个网络包,如果经过了超过 64 个中间路由节点,则认为目的地不可达,中间路由器会将此包抛弃掉
0x 十进制
40 ==> 64
继续的 8bit 为协议域,用于指代上一层协议类型
此处的值为 0x11,对应十进制的 17,而 17 是 UDP 协议的代号,因此可以知道这个网络包所用的传输层协议是 UDP,而非 TCP
TCP 的协议号是 6,ICMP 的协议号是 1
0x 十进制
11 ==> 17
接下来的 2 个字节表示 IP 首部校验和,此处计算出来的结果是 3c93
0x 十进制
3c93 ==> 15507
再往下就是大家非常熟悉的 4 字节的 IP 源地址,即 74 ff f5 ce,转换成 IP 地址则为 116.255.245.206
0x 十进制
74ff f5ce ==> 116.255.245.206
再下面的 4 字节则为 IP 目的地址,即 08 08 08 08,转换成 IP 地址则为 8.8.8.8,这是著名的 Google-DNS 服务器地址
至此,网络层 IP 协议的首部 20 字节已经分析完了,再向下我们即将进入传输层 UDP 协议的包分析阶段。
0x 十进制
0808 0808 ==> 8.8.8.8
- UDP 首部解析
0x0000: 4500 003b c341 0000 4011 3c93 74ff f5ce E..;.A..@.<.t...
0x0010: 0808 0808 bb44 0035 0027 b457 58f0 0100 .....D.5.'.WX...
0x0020: 0001 0000 0000 0000 0377 7777 0562 6169 .........www.bai
0x0030: 6475 0363 6f6d 0000 0100 01 du.com.....
相对于 TCP 包来说,UDP 包的首部还是比较简单的,总共只有 8 个字节,是 UDP 首部部分。UDP 首部的前 2 个字节为源端口,此处为 bb 44,即 47940,而接下来的 2 字节为目的端口,值为 00 35,即 53(DNS 服务)。
0x 十进制
bb44 ==> 47940
0035 ==> 53
而接下来的 2 字节则表示 UDP 包的总长度(报头+数据部分)
此处的值为 00 27,这算成十进制则为 39
表示此 UDP 包的总长度为 39 字节,减去首部的 8 字节外,还有 31 字节来存储真正要传输的数据
0x 十进制
0027 ==> 39
而 UDP 首部的最后两个字节则是校验和部分,此处的值为 0xb457
0x 十进制
b457 ==> 46167
- 数据分析
再向下的部分,则是应用层协议的内容(本例中是 DNS 协议)了
如果你有兴趣,可以继续了解下 DNS 协议、HTTP 协议、FTP 协议等众多的应用层协议
这非常有利于大家在学习协议、追查网络问题时,透过现象看本质
0x0000: 4500 003b c341 0000 4011 3c93 74ff f5ce E..;.A..@.<.t...
0x0010: 0808 0808 bb44 0035 0027 b457 58f0 0100 .....D.5.'.WX...
0x0020: 0001 0000 0000 0000 0377 7777 0562 6169 .........www.bai
0x0030: 6475 0363 6f6d 0000 0100 01 du.com.....
文章作者: Escape
文章链接: https://www.escapelife.site/posts/365ce3c5.html
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Escape !
相关推荐
- 5款Syslog集中系统日志常用工具对比推荐
-
一、为何要集中管理Syslog?Syslog由Linux/Unix系统及其他网络设备生成,广泛分布于整个网络。因其包含关键信息,可用于识别网络中的恶意活动,所以必须对其进行持续监控。将Sys...
- 跨平台、多数据库支持的开源数据库管理工具——DBeaver
-
简介今天给大家推荐一个开源的数据库管理工具——DBeaver。它支持多种数据库系统,包括Mysql、Oracle、PostgreSQL、SLQLite、SQLServer等。DBeaver的界面友好...
- 强烈推荐!数据库管理工具:Navicat Premium 16.3.2 (64位)
-
NavicatPremium,一款集数据迁移、数据库管理、SQL/查询编辑、智能设计、高效协作于一体的全能数据库开发工具。无论你是MySQL、MariaDB、MongoDB、SQLServer、O...
- 3 年 Java 程序员还玩不转 MongoDB,网友:失望
-
一、什么场景使用MongoDB?...
- 拯救MongoDB管理员的GUI工具大赏:从菜鸟到极客的生存指南
-
作为一名在NoSQL丛林中披荆斩棘的数据猎人,没有比GUI工具更称手的瑞士军刀了。本文将带你围观五款主流MongoDB管理神器的特性与暗坑,附赠精准到扎心的吐槽指南一、MongoDBCompass:...
- mongodb/redis/neo4j 如何自己打造一个 web 数据库可视化客户端?
-
前言最近在做neo4j相关的同步处理,因为产线的可视化工具短暂不可用,发现写起来各种脚本非常麻烦。...
- solidworks使用心得,纯干货!建议大家收藏
-
SolidWorks常见问题...
- 统一规约-关乎数字化的真正实现(规范统一性)
-
尽管数字化转型的浪潮如此深入人心,但是,对于OPCUA和TSN的了解却又甚少,这难免让人质疑其可实现性,因为,如果缺乏统一的语义互操作规范,以及更为具有广泛适用的网络与通信,则数字化实际上几乎难以具...
- Elasticsearch节点角色配置详解(Node)
-
本篇文章将介绍如下内容:节点角色简介...
- 产前母婴用品分享 篇一:我的母婴购物清单及单品推荐
-
作者:DaisyH8746在张大妈上已经混迹很久了,有事没事看看“什么值得买”已渐渐成了一种生活习惯,然而却从来没有想过自己要写篇文章发布上来,直到由于我产前功课做得“太过认真”(认真到都有点过了,...
- 比任何人都光彩照人的假期!水润、紧致的肌肤护理程序
-
图片来源:谜尚愉快的假期临近了。身心振奋的休假季节。但是不能因为这种心情而失去珍贵的东西,那就是皮肤健康。炙热的阳光和强烈的紫外线是使我们皮肤老化的主犯。因此,如果怀着快乐的心情对皮肤置之不理,就会使...
- Arm发布Armv9边缘AI计算平台,支持运行超10亿参数端侧AI模型
-
中关村在线2月27日消息,Arm正式发布Armv9边缘人工智能(AI)计算平台。据悉,该平台以全新的ArmCortex-A320CPU和领先的边缘AI加速器ArmEthos-U85NPU为核心...
- 柔性——面向大规模定制生产的数字化实现的基本特征
-
大规模定制生产模式的核心是柔性,尤其是体现在其对定制的要求方面。既然是定制,并且是大规模的定制,对于制造系统的柔性以及借助于数字化手段实现的柔性,就提出了更高的要求。面向大规模定制生产的数字化业务管控...
- 创建PLC内部标准——企业前进的道路
-
作者:FrankBurger...
- 标准化编程之 ----------- 西门子LPMLV30测试总结
-
PackML乃是由OMAC开发且被ISA所采用的自动化标准TR88.00.02,能够更为便捷地传输与检索一致的机器数据。PackML的主要宗旨在于于整个工厂车间倡导通用的“外观和感觉”,...
你 发表评论:
欢迎- 一周热门
-
-
Linux:Ubuntu22.04上安装python3.11,简单易上手
-
宝马阿布达比分公司推出独特M4升级套件,整套升级约在20万
-
MATLAB中图片保存的五种方法(一)(matlab中保存图片命令)
-
别再傻傻搞不清楚Workstation Player和Workstation Pro的区别了
-
Linux上使用tinyproxy快速搭建HTTP/HTTPS代理器
-
如何提取、修改、强刷A卡bios a卡刷bios工具
-
Element Plus 的 Dialog 组件实现点击遮罩层不关闭对话框
-
日本组合“岚”将于2020年12月31日停止团体活动
-
SpringCloud OpenFeign 使用 okhttp 发送 HTTP 请求与 HTTP/2 探索
-
tinymce 号称富文本编辑器世界第一,大家同意么?
-
- 最近发表
-
- 5款Syslog集中系统日志常用工具对比推荐
- 跨平台、多数据库支持的开源数据库管理工具——DBeaver
- 强烈推荐!数据库管理工具:Navicat Premium 16.3.2 (64位)
- 3 年 Java 程序员还玩不转 MongoDB,网友:失望
- 拯救MongoDB管理员的GUI工具大赏:从菜鸟到极客的生存指南
- mongodb/redis/neo4j 如何自己打造一个 web 数据库可视化客户端?
- solidworks使用心得,纯干货!建议大家收藏
- 统一规约-关乎数字化的真正实现(规范统一性)
- Elasticsearch节点角色配置详解(Node)
- 产前母婴用品分享 篇一:我的母婴购物清单及单品推荐
- 标签列表
-
- dialog.js (57)
- importnew (44)
- windows93网页版 (44)
- yii2框架的优缺点 (45)
- tinyeditor (45)
- qt5.5 (60)
- windowsserver2016镜像下载 (52)
- okhttputils (51)
- android-gif-drawable (53)
- 时间轴插件 (56)
- docker systemd (65)
- slider.js (47)
- android webview缓存 (46)
- pagination.js (59)
- loadjs (62)
- openssl1.0.2 (48)
- velocity模板引擎 (48)
- pcre library (47)
- zabbix微信报警脚本 (63)
- jnetpcap (49)
- pdfrenderer (43)
- fastutil (48)
- uinavigationcontroller (53)
- bitbucket.org (44)
- python websocket-client (47)