Tcpdump网络/命令行抓包工具

1
2
3
4
5
6
7
8
tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息


# tcpdump安装
apt-get install tcpdump

# 版本查看
tcpdump --h

1. tcpdump常用参数

参数 含义
-a 将网络地址和广播地址转变成名字
-c 在收到指定的包的数目后,tcpdump就会停止 ;
-d 将匹配信息包的代码以人们能够理解的汇编格式给出;以可阅读的格式输出
-dd 将匹配信息包的代码以c语言程序段的格式给出;
-ddd 将匹配信息包的代码以十进制的形式给出
-e 在输出行打印出数据链路层的头部信息;
-f 将外部的Internet地址以数字的形式打印出来
-I 使标准输出变为缓冲行形式;
-n 直接显示IP地址,不显示名称;
-nn 端口名称显示为数字形式,不显示名称
-t 在输出的每一行不打印时间戳;
-v 输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息;
-vv 输出详细的报文信息;
-F 从指定的文件中读取表达式,忽略其它的表达式
-i 指定监听的网络接口;
-r 从指定的文件中读取包(这些包一般通过-w选项产生);
-w 直接将包写入文件中,并不分析和打印出来 ;
-T 将监听到的包直接解释为指定的类型的报文,常见的类型有rp (远程过程调用)和snmp(简单 网络管理协议;)

2. 常用使用参数选项

2.1 截获主机收到和发出的所有数据包

1
2
3
# 基础格式:时间 数据包类型 源IP 端口/协议 > 目标IP 端口/协议 协议详细信息
# tcpdump
17:25:41.303610 IP 172.19.0.48.60415 > dns.google.domain: 63411+ PTR? 230.12.19.172.in-addr.arpa. (44)

2.2 指定抓包数量

1
2
3
4
5
6
7
8
9
# ping jwgod.com

# tcpdump -c 2
17:32:58.860836 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25507, seq 31, length 64
17:32:58.861387 IP 172.19.0.48.55842 > dns.google.domain: 8121+ PTR? 153.108.199.185.in-addr.arpa. (46)
17:32:58.910778 IP dns.google.domain > 172.19.0.48.55842: 8121 1/0/0 PTR cdn-185-199-108-153.github.com. (90)
17:32:58.910955 IP 172.19.0.48.36070 > dns.google.domain: 32272+ PTR? 48.0.19.172.in-addr.arpa. (42)
17:32:58.912340 IP cdn-185-199-108-153.github.com > 172.19.0.48: ICMP echo reply, id 25507, seq 31, length 64
17:32:59.862496 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25507, seq 32, length 64

2.3 将抓包信息写入文件 -w

1
2
# tcpdump -c 10 -w tcpdump_test.log 
备注:保存的文件不是文本格式,不能直接查看。tcpdump保存的文件的格式是几乎所有主流的抓包工具软件都可以读取。所以可以使用更易读的图形界面工具来查看记录文件

2.4 读取记录文件 -r

1
# tcpdump -r tcpdump_test.log

2.5 打印出所有可工作的接口 -D

1
2
3
4
5
6
7
8
9
# tcpdump -D
1.eth0 [Up, Running]
2.lo [Up, Running, Loopback]
3.any (Pseudo-device that captures on all interfaces) [Up, Running]
4.bluetooth-monitor (Bluetooth Linux Monitor) [none]
5.nflog (Linux netfilter log (NFLOG) interface) [none]
6.nfqueue (Linux netfilter queue (NFQUEUE) interface) [none]

# 其中网卡为eth0

2.6 指定监控的网卡 -i

1
2
3
# tcpdump -i eth0

备注:如果不指定网卡,默认tcpdump只会监视第一个网络接口,一般是eth0

2.7 显示更详细的数据包信息 -v -vv

1
2
3
4
5
6
7
8
9
10
11
12
# tcpdump -i eth0 -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:42:48.251299 IP (tos 0x0, ttl 64, id 23778, offset 0, flags [DF], proto ICMP (1), length 84)
172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25517, seq 367, length 64
17:42:48.251903 IP (tos 0x0, ttl 64, id 45769, offset 0, flags [DF], proto UDP (17), length 74)
172.19.0.48.56590 > dns.google.domain: 21380+ PTR? 153.108.199.185.in-addr.arpa. (46)
17:42:48.302119 IP (tos 0x0, ttl 51, id 5314, offset 0, flags [none], proto ICMP (1), length 84)
cdn-185-199-108-153.github.com > 172.19.0.48: ICMP echo reply, id 25517, seq 367, length 64
# 输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息;

# tcpdump -i eth0 -vv
# 输出详细的报文信息;

2.8 不使用域名反解 -n

1
2
3
4
5
# 使用-n后,tcpdump会直接显示IP地址,不会显示域名
# tcpdump -i eth0 -n
17:49:01.954428 IP 172.19.0.48 > 185.199.108.153: ICMP echo request, id 25517, seq 740, length 64
17:49:02.005387 IP 185.199.108.153 > 172.19.0.48: ICMP echo reply, id 25517, seq 740, length 64
17:49:02.954617 IP 172.19.0.48 > 185.199.108.153: ICMP echo request, id 25517, seq 741, length 64

2.9 增加抓包时间戳 -tttt选项

1
2
3
4
5
6
# tcpdump -i eth0 -tttt
2024-07-18 17:53:02.409496 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25517, seq 980, length 64
2024-07-18 17:53:02.409876 IP 172.19.0.48.38224 > dns.google.domain: 9234+ PTR? 153.108.199.185.in-addr.arpa. (46)
2024-07-18 17:53:02.460298 IP cdn-185-199-108-153.github.com > 172.19.0.48: ICMP echo reply, id 25517, seq 980, length 64

备注:时间戳信息的显示格式:hh:mm:ss.frac (nt: 小时:分钟:秒.)

3. 条件过滤

3.1 过滤–指定需要抓取的协议

1
2
3
4
5
6
7
8
9
10
11
备注:tcpdump可以只抓某种协议的包,支持指定以下协议:「ip,ip6,arp,tcp,udp,wlan」等
# tcpdump udp
17:59:19.899371 IP 172.19.0.1.50523 > 239.255.255.250.1900: UDP, length 175
17:59:20.906469 IP 172.19.0.1.50523 > 239.255.255.250.1900: UDP, length 175

# tcpdump icmp
18:00:04.209766 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25517, seq 1401, length 64
18:00:04.260576 IP cdn-185-199-108-153.github.com > 172.19.0.48: ICMP echo reply, id 25517, seq 1401, length 64

# tcpdump tcp
# tcpdump arp

3.2 过滤–指定协议的端口号

1
2
3
4
5
备注:使用port参数,用于指定端口号。
# tcpdump tcp port 80

备注:使用portrange参数,用于指定端口范围。
# tcpdump tcp portrange 1-1024

3.3 过滤–指定源与目标

1
2
3
4
5
6
备注:
src 表示源。
dst 表示目标。

# tcpdump src port 8080
# tcpdump dst port 80

3.4 过滤–指定特定主机的消息包

1
2
备注:若使用了host参数使用了计算机名或域名。例tcpdump host jwgod.com ,则无法再使用-n选项
# tcpdump host jwgod.com

3.5 过滤–指定数据包大小

1
2
3
4
5
6
7
备注:使用greater(大于)与less(小于)可以指定数据包大小的范围。

# 只抓取大于1000字节的数据包
# tcpdump greater 1000

# 只抓取小于10字节的数据包
# tcpdump less 10

4. 逻辑表达式

4.1 逻辑与

1
2
3
4
备注:逻辑与关系,使用and

# tcpdump tcp and host 192.168.64.11
# tcpdump tcp and src 192.168.64.11 and port 8080

4.2 逻辑或

1
2
3
备注:逻辑或关系,使用or

# tcpdump host 192.168.64.11 or 192.168.64.12

4.3 逻辑非

1
2
3
4
备注:逻辑非关系,使用not,也可以使用 !,若使用 ! 必须与其后面的字符隔开一个空格

# tcpdump not tcp port 22
# tcpdump ! tcp port 22

4.4 括号

1
2
3
4
5
6
备注:括号需要使用在引号内,或转意使用。否则会报错

# 抓取非22端口,且主机为192.168.64.11 和 192.168.64.12的TCP数据包
# tcpdump not tcp port 22 and host 192.168.64.11or192.168.64.12
# tcpdump "not tcp port 22 and host (192.168.64.11 or 192.168.64.12)"
# tcpdump not tcp port 22 and host "(192.168.64.11 or 192.168.64.12)"

5. 其他使用实例

5.1 打印所有进入或离开jwgod.com的数据包

1
# tcpdump host jwgod.com

5.2 截获主机192.168.64.11 和主机192.168.64.12 或192.168.64.13的通信

1
# tcpdump host 192.168.64.11 and  (192.168.64.12 or 192.168.64.13 ) 

5.3 想要获取主机192.168.64.11除了和主机192.168.64.12之外所有主机通信的ip包

1
# tcpdump ip host 192.168.64.11 and ! 192.168.64.12

5.4 监视所有送到主机hostname的数据包

1
# tcpdump -i eth0 dst host hostname

5.5 获取主机192.168.64.11接收或发出的telnet包

1
2
# 23为telnet的端口
# tcpdump tcp port 23 and host 92.168.64.11

5.6 监视本机的udp 123 端口

1
2
# 123 为ntp的服务端口
# tcpdump udp port 123

5.7 使用tcpdump抓取HTTP包

1
2
3
4
5
6
# tcpdump  -XvvennSs 0 -i eth0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854 

备注:
0x4745 为"GET"前两个字母"GE",
0x4854 为"HTTP"前两个字母"HT"。
tcpdump 对截获的数据并没有进行彻底解码,数据包内的大部分内容是使用十六进制的形式直接打印输出的,显然这不利于分析网络故障,通常的解决办法是先使用带-w参数的tcpdump 截获数据并保存到文件中,然后再使用其他程序(如Wireshark)进行解码分析。当然也应该定义过滤规则,以避免捕获的数据包填满整个硬盘

6. 查看数据包完整内容

1
tcpdump默认不显示数据包的详细内容

6.1 使用-A参数能以ASCII码显示数据包

1
2
3
4
5
6
7
8
9
# 只抓取1个数据包,并显示其内容。
# tcpdump -c 1 -A
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:24:55.217307 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25535, seq 629, length 64
E..TP.@.@..d...0..l....Sc..uw..f.....P...................... !"#$%&'()*+,-./01234567
1 packet captured
30 packets received by filter
0 packets dropped by kernel

6.2 使用-X参数能16进制数与ASCII码共同显示数据包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 只抓取1个数据包,并显示其内容。
# tcpdump -c 1 -X
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:25:46.290934 IP 172.19.0.48 > cdn-185-199-108-153.github.com: ICMP echo request, id 25535, seq 680, length 64
0x0000: 4500 0054 5a7a 4000 4001 0d8b ac13 0030 E..TZz@.@......0
0x0010: b9c7 6c99 0800 2f01 63bf 02a8 aaed 9866 ..l.../.c......f
0x0020: 0000 0000 5c70 0400 0000 0000 1011 1213 ....\p..........
0x0030: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 .............!"#
0x0040: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 $%&'()*+,-./0123
0x0050: 3435 3637 4567
1 packet captured
17 packets received by filter
0 packets dropped by kernel

7. tcpdump 与 wireshark

1
2
3
通过Tcpdump抓取的数据包分析比较麻烦,要想很方便的分析数据包, 我们可以用Tcpdump + Wireshark 的完美组合实现:在 Linux 里抓包,然后在Windows 里分析包,保存数据包为wireshark能识别的文件

# tcpdump tcp -i eth0 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.64.0/24 -w ./target.cap
参数 含义
tcp ip icmp arp rarp 和 tcp、udp、icmp这些选项等都要放到第一个参数的位置,用来过滤数据报的类型
-i eth0 只抓经过接口eth0的包
-t 不显示时间戳
-s 0 抓取数据包时默认抓取长度为68字节。加上-S 0 后可以抓到完整的数据包
-c 100 只抓取100个数据包
dst port ! 22 不抓取目标端口是22的数据包
src net 192.168.64.0/24 数据包的源网络地址为192.168.1.0/24
-w ./target.cap 保存成cap文件,方便用ethereal(即wireshark)分析

wireshark安装

1
2
3
4
5
下载地址:https://2.na.dl.wireshark.org/win64/Wireshark-4.2.6-x64.exe

# 抓包
for i in `seq 1000000` ; do curl https://open.youzanyun.com/auth/token; echo \ $i; sleep 1;done
tcpdump -XvvennSs 0 -i ens18 host open.youzanyun.com -w tcpdump_test-ok.cap

三次握手失败

image-20240719143438152

三次握手成功

image-20240719153755463

Flags 标识符

1
2
3
4
5
6
7
使用 tcpdump 抓包后,会遇到的 TCP 报文 Flags,有以下几种:

- `[S]` : SYN(开始连接)
- `[P]` : PSH(推送数据)
- `[F]` : FIN (结束连接)
- `[R]` : RST(重置连接)
- `[.]` : 没有 Flag (意思是除上面四种类型外的其他情况,有可能是 ACK 也有可能是 URG)

8. 抓包实战应用例子

8.1 提取 HTTP 的 User-Agent

1
2
3
4
5
6
# 从 HTTP 请求头中提取 HTTP 的 User-Agent:
# tcpdump -nn -A -s1500 -l | grep "User-Agent:"


# 通过 egrep 可以同时提取User-Agent 和主机名(或其他头文件):
# tcpdump -nn -A -s1500 -l | egrep -i 'User-Agent:|Host:'

8.2 抓取 HTTP GET 和 POST 请求

1
2
3
4
5
6
7
8
9
10
11
# 抓取 HTTP GET 请求包:
# tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
or
# tcpdump -vvAls0 | grep 'GET'

# 可以抓取 HTTP POST 请求包:
# tcpdump -s 0 -A -vv 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354'
or
# tcpdump -vvAls0 | grep 'POST'

备注:该方法不能保证抓取到 HTTP POST 有效数据流量,因为一个 POST 请求会被分割为多个 TCP 数据包

8.3 找出发包数最多的 IP

1
2
3
4
5
6
# 找出一段时间内发包最多的 IP,或者从一堆报文中找出发包最多的 IP,可以使用下面的命令:
# tcpdump -nnn -t -c 200 | cut -f 1,2,3,4 -d '.' | sort | uniq -c | sort -nr | head -n 20

- cut -f 1,2,3,4 -d ‘.’: 以 `.` 为分隔符,打印出每行的前四列。即 IP 地址。
- sort | uniq -c: 排序并计数
- sort -nr: 按照数值大小逆向排序

8.4 抓取 DNS 请求和响应

1
2
# DNS 的默认端口是 53,因此可以通过端口进行过滤
# tcpdump -i any -s0 port 53

8.5 切割 pcap 文件

1
2
3
4
# 当抓取大量数据并写入文件时,可以自动切割为多个大小相同的文件。例如,下面的命令表示每 3600 秒创建一个新文件 `capture-(hour).pcap`,每个文件大小不超过 `200*1000000` 字节:
# tcpdump -w /tmp/capture-%H.pcap -G 3600 -C 200

备注:这些文件的命名为 `capture-{1-24}.pcap`,24 小时之后,之前的文件就会被覆盖。

8.6 提取 HTTP POST 请求中的密码

1
2
# 从 HTTP POST 请求中提取密码和主机名:
# tcpdump -s 0 -A -n -l | egrep -i "POST /|pwd=|passwd=|password=|Host:"

8.7 提取 HTTP 请求的 URL

1
2
# 提取 HTTP 请求的主机名和路径:
# tcpdump -s 0 -v -n -l | egrep -i "POST /|GET /|Host:"

8.8 抓取 HTTP 有效数据包

1
2
# 抓取 80 端口的 HTTP 有效数据包,排除 TCP 连接建立过程的数据包(SYN / FIN / ACK):
# tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

8.9 结合 Wireshark 进行分析

1
2
3
4
5
6
7
8
9
# 通常 Wireshark(或 tshark)比 tcpdump 更容易分析应用层协议。一般的做法是在远程服务器上先使用 tcpdump 抓取数据并写入文件,然后再将文件拷贝到本地工作站上用 Wireshark 分析。

# 还有一种更高效的方法,可以通过 ssh 连接将抓取到的数据实时发送给 Wireshark 进行分析。以 MacOS 系统为例,可以通过 brew cask install wireshark 来安装,然后通过下面的命令来分析:
# ssh root@remotesystem 'tcpdump -s0 -c 1000 -nn -w - not port 22' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -

# 例如,如果想分析 DNS 协议,可以使用下面的命令:
# ssh root@remotesystem 'tcpdump -s0 -c 1000 -nn -w - port 53' | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i -
-c 选项用来限制抓取数据的大小。如果不限制大小,就只能通过 ctrl-c 来停止抓取,这样一来不仅关闭了 tcpdump,也关闭了 wireshark。