tcpdump
tcpdump man
tcpdump 须在管理员权限下运行。
1 2 # tcpdump listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
输出结果表明 tcpdump 的监听网卡为 ens33
。
默认截断大小为 262144 字节(随版本而改变),超过该数字报文会被截断。
使用 ifconfig
查看其他网卡:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # ifconfig ens33 Link encap:Ethernet HWaddr 00:0c:29:48:09:a9 inet addr:192.168.248.128 Bcast:192.168.248.255 Mask:255.255.255.0 inet6 addr: fe80::555a:9e00:3f14:e7f/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:12058 errors:0 dropped:0 overruns:0 frame:0 TX packets:4911 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:9115911 (9.1 MB) TX bytes:577567 (577.5 KB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:1110 errors:0 dropped:0 overruns:0 frame:0 TX packets:1110 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:1022006 (1.0 MB) TX bytes:1022006 (1.0 MB)
-i 指定网卡
上面默认监听网卡是 ens33
,我们也可以指定为 lo
:
1 2 tcpdump -i lo listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
-i any
可以监听所有网卡。
-nn 直接显示IP和端口号
1 2 3 4 5 listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes 01:12:54.640796 IP localhost.44438 > localhost.12345: Flags [S], seq 1028792545, win 65495, options [mss 65495,sackOK,TS val 1381449987 ecr 0,nop,wscale 7], length 0 01:12:54.640834 IP localhost.12345 > localhost.44438: Flags [S.], seq 3925511357, ack 1028792546, win 65483, options [mss 65495,sackOK,TS val 1381449987 ecr 1381449987,nop,wscale 7], length 0 01:12:54.640870 IP localhost.44438 > localhost.12345: Flags [.], ack 1, win 512, options [nop,nop,TS val 1381449987 ecr 1381449987], length 0
监听环回网卡时,我们运行自己编写的简易 TCP 服务器端和客户端的回射程序,结果输出以上三次握手内容。其中主机地址为 localhost
,由于 server 和 client 都在一台主机,所以都为 localhost
。如果服务器的端口为著名端口(如 ssh 为 22 号端口),那么 22 也会显示为 ssh。若想直接显示 IP 和端口号,则使用 -nn
命令:
1 2 # tcpdump -i lo -nn 01:14:54.615811 IP 127.0.0.1.44438 > 127.0.0.1.12345: Flags [P.], seq 1028792546:1028792548, ack 3925511358, win 512, options [nop,nop,TS val 1381569983 ecr 1381449987], length 2
-n 不将IP转换为域名
不讲 IP 转为域名,则可以省去 DNS 查询,输出速度会快很多。
过滤主机
抓取所有经过 eth1,目的或源地址是 192.168.1.1 的网络数据
1 # tcpdump -i eth1 host 192.168.1.1
1 # tcpdump -i eth1 src host 192.168.1.1
1 # tcpdump -i eth1 dst host 192.168.1.1
1 # tcpdump -i eth1 dest host "baidu.com"
过滤端口
抓取所有经过 eth1,目的或源端口是 25 的网络数据
1 # tcpdump -i eth1 port 25
1 # tcpdump -i eth1 src port 25
1 # tcpdump -i eth1 dst port 25
指定端口范围:portrange
1 # tcpdump -i lo portrange 10000-20000
对于著名端口,可直接用应用层协议替代,相当于宏:
网段过滤
1 2 3 # tcpdump -i eth1 net 192.168 # tcpdump -i eth1 src net 192.168 # tcpdump -i eth1 dst net 192.168.0.0/16
协议过滤
1 2 3 # tcpdump arp # tcpdump ip # tcpdump tcp
不能直接过滤协议,如下
而应该
常用表达式
1 2 3 非 : ! 或 not 且 : && 或 and 或 : || 或 or
1 2 # tcpdump -i lo -nn tcp && dst port 12345 && src host 127.0.0.1 # tcpdump -i lo -nn tcp and dst port 12345 and src host 127.0.0.1
有时条件比较复杂的需要用括号:
1 2 # tcpdump -i eth1 '((tcp) and (! port 80) and ((dst host 192.168.1.254) or (dst host 192.168.1.200)))' 抓取所有经过eth1,目的地址是192.168.1.254或192.168.1.200,并且端口不是80的TCP数据
如果使用括号,则整个表达式需要用 ''
或 ""
包住。
包头过滤
1 2 3 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
IP报头格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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 \bit +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0 |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4 | Identification |Flags| Fragment Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12 | Time to Live | Protocol | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16 | Source Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 20 | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24 | Options | Padding | <-- optional +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 28 | DATA ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \byte
TCP报头格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 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 \bit +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0 | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4 | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 8 | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |C|E|U|A|P|R|S|F| | 12 | Offset| Res. |W|C|R|C|S|S|Y|I| Window | | | |R|E|G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 16 | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 20 | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 24 | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \byte
1 2 # tcpdump -i lo "tcp[2:2]=12345" 只显示目的端口号为12345的报文
TCP标记定义在TCP头的第 13 个字节:
1 2 # tcpdump -i lo "src port 12345 && tcp[13]&1 = 1" 只显示目的端口号为12345的FIN报文
TCP标记宏可以替代数值:
tcpflags
, tcp-fin
, tcp-syn
, tcp-rst
, tcp-push
, tcp-push
, tcp-ack
, tcp-urg
1 # tcpdump -i lo "dst port 12345 && tcp[tcpflags]&tcp-fin=tcp-fin"
-w 输出到文件、-r 读取文件
1 # tcpdump tcp -w test.cap
把信息输出到 test.cap 文件。将文件保存为 cap
或 pcap
类型就能方便地使用 wireshark 打开并分析:
1 # tcpdump tcp -r test.cap
读取 test.cap
文件并打印在终端,同时也可以使用过滤规则:
1 # tcpdump tcp -r test.cap port 12345
输出时间
-t
:在每行的输出中不输出时间
-tt
:在每行的输出中会输出时间戳
-ttt
:输出每两行打印的时间间隔(以毫秒为单位)
-tttt
:在每行打印的时间戳之前添加日期的打印
1 2 3 4 5 6 7 8 9 10 11 12 # tcpdump -t dst "baidu.com" IP 192.168.248.128 > 39.156.66.10: ICMP echo request, id 11930, seq 1650, length 64 # tcpdump -tt dst "baidu.com" 1680352032.093467 IP 192.168.248.128 > 39.156.66.10: ICMP echo request, id 11930, seq 1662, length 64 # tcpdump -ttt dst "baidu.com" 00:00:00.000000 IP 192.168.248.128 > 39.156.66.10: ICMP echo request, id 11930, seq 1672, length 64 00:00:01.002438 IP 192.168.248.128 > 39.156.66.10: ICMP echo request, id 11930, seq 1673, length 64 # tcpdump -tttt dst "baidu.com" 2023-04-01 05:27:30.131073 IP 192.168.248.128 > 39.156.66.10: ICMP echo request, id 11930, seq 1680, length 64
-v 展示详细信息
-v
:产生详细的输出。比如包的TTL,id标识,数据包长度,以及IP包的一些选项:
1 2 3 4 root@ubuntu:/home/butcher/Documents# tcpdump -v dst "baidu.com" tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes 05:36:46.543701 IP (tos 0x0, ttl 64, id 44013, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.248.128 > 39.156.66.10: ICMP echo request, id 12115, seq 7, length 64
-c 指定接收报文个数
1 2 3 4 5 6 7 # tcpdump -v -c 3 05:46:32.275269 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 192.168.248.2 tell 192.168.248.1, length 46 05:46:32.276545 IP (tos 0x0, ttl 64, id 50690, offset 0, flags [DF], proto UDP (17), length 72) 192.168.248.128.34566 > 192.168.248.2.domain: 39118+ PTR? 2.248.168.192.in-addr.arpa. (44) 05:46:32.280758 IP (tos 0x0, ttl 128, id 35219, offset 0, flags [none], proto UDP (17), length 127) 192.168.248.2.domain > 192.168.248.128.34566: 39118 NXDomain 0/1/0 (99) 3 packets captured
抓满指定数量的报文后自动停止。
-C -W 分文件写入
1 # tcpdump -C 1 -W 4 -w test
-C 和 -w 配套使用,后者将抓包情况写入文件,前者指定每个文件的最大大小,单位为 1MB(小文件利于分析)。
-C 1
:指定单个文件最大为 1MB
-W
:指定最多写 4 个文件
-w
:写入文件
每个文件会依次添加后缀:test1、test2、test3、test4 。注意,如果写满这 4 个文件后,数据还在持续,那么会重新覆盖这 4 个文件并继续写入,而不会新建文件。
-Q 指定方向
-Q in :只显示收到的数据
-Q out :只显示发出的数据
1 2 3 4 # tcpdump -Q in 06:04:34.157713 IP 192.168.248.1.50277 > 239.255.255.250.1900: UDP, length 175 06:04:34.163603 IP 192.168.248.2.domain > 192.168.248.128.34566: 27092 NXDomain 0/1/0 (103) 06:04:35.003369 IP 180.101.49.186.https > 192.168.248.128.33644: Flags [.], ack 769671203, win 64240, length 0
-s 指定截取大小
-s
指定每个包捕获的长度、单位是 byte,而不是默认的 262144 字节;如果超过了设定的大小限制,包就会被截断,并在打印行出现[|proto]这种标识,这个proto就是被截断的报文的协议名字。但是抓取越长,包的处理时间越长,并且会减少 tcpdump 可缓存的数据包的数量,从而会导致数据包的丢失,所以在能抓取我们想要的包的前提下,抓取长度越小越好,一般只抓报头 ,抓 80 个字节一般就能包含 TCP 层、IP 层、链路层。
-s 0
使用默认长度 262144。
-e 显示链路层信息
1 2 3 # tcpdump -e 06:49:36.315000 00:0c:29:48:09:a9 (oui Unknown) > 00:50:56:fb:6d:e0 (oui Unknown), ethertype IPv4 (0x0800), length 54: 192.168.248.128.33644 > 180.101.49.186.https: Flags [.], ack 565954419, win 65535, length 0
-F 指定过滤过滤表达式文件
有些过滤表达式经常用,但又很冗长,每次输入都很麻烦。所以可以保存为文件,每次 tcpdump 时指定该文件为过滤规则:
该命令行中的其他命令会被忽略。
less,greater 指定大小
-X 打印数据内容
-X
除了打印每个数据包的头之外,还可以用十六进制和ASCII打印每个数据包的数据(不包括链路级头,-XX
可包含):