1. 抓包实战应用例子
1.1 提取 HTTP 的 User-Agent
从 HTTP 请求头中提取 HTTP 的 User-Agent:
$ tcpdump -nn -A -s1500 -l | grep "User-Agent:"
通过 egrep(支持正则的grep) 可以同时提取User-Agent 和主机名(或其他头文件):
$ tcpdump -nn -A -s1500 -l | egrep -i 'User-Agent:|Host:'
1.2 抓取 HTTP GET 和 POST 请求
抓取 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 数据包。
1.3 找出发包数最多的 IP
找出一段时间内发包最多的 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 : 按照数值大小逆向排序
1.4 抓取 DNS 请求和响应
DNS 的默认端口是 53,因此可以通过端口进行过滤
$ tcpdump -i any -s0 port 53
1.5 切割 pcap 文件
当抓取大量数据并写入文件时,可以自动切割为多个大小相同的文件。例如,下面的命令表示每 3600 秒创建一个新文件 capture-(hour).pcap,每个文件大小不超过 200*1000000 字节:
$ tcpdump -w /tmp/capture-%H.pcap -G 3600 -C 200
这些文件的命名为 capture-{1-24}.pcap,24 小时之后,之前的文件就会被覆盖。
1.6 提取 HTTP POST 请求中的密码
从 HTTP POST 请求中提取密码和主机名:
$ tcpdump -s 0 -A -n -l | egrep -i "POST /|pwd=|passwd=|password=|Host:"
1.7 提取 HTTP 请求的 URL
提取 HTTP 请求的主机名和路径:
$ tcpdump -s 0 -v -n -l | egrep -i "POST /|GET /|Host:"
1.8 抓取 HTTP 有效数据包
抓取 80 端口的 HTTP 有效数据包,排除 TCP 连接建立过程的数据包(SYN / FIN / ACK):
$ tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
1.9 结合 Wireshark 进行分析
通常 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。