tcpdump 生产网Troubleshooting之实用篇
tcpdump 生产网Troubleshooting之实用篇
-
同类参考: https://github.com/cilium/cilium - 同样是基于 linux kernel eBPF,Kubernetes 生态下最有潜力的高性能 CNI 插件。
-
源码分析 Linux kernel bpf: https://github.com/torvalds/linux/blob/v5.9/kernel/bpf/bpf_struct_ops.c
1. 基础
- 安装 tcpdump
sudo apt-get install tcpdump # Focal Linux(Ubuntu/Debian)
sudo yum install tcpdump # Redhat Linux(CentOS/Oracle Linux)
- 查看 tcpdump 示例
sudo man tcpdump | less -Ip examples
2. 应用层数据包(实用)
2.1 捕获 HTTP 包
- 捕获 HTTP GET 请求(原理:GET 的十六进制是 0x47455420)
sudo tcpdump -s 0 -A 'tcp dst port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
- 捕获 HTTP POST 请求
sudo tcpdump -s 0 -A 'tcp dst port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354)'
- 捕获 HTTP 请求响应头及数据
# 文本输出
sudo tcpdump -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
# HEX 输出
sudo tcpdump -X -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
2.2 捕获 SMTP 包
- 捕获数据区开始为MAIL的包,MAIL的十六进制为 0x4d41494c。
sudo tcpdump -i eth0 '((port 25) and (tcp[(tcp[12]>>2):4] = 0x4d41494c))'
2.3 捕获 SSH 包
sudo tcpdump -i eth0 'tcp[(tcp[12]>>2):4] = 0x5353482D'
SSH-的十六进制是 0x5353482D,抓老版本的 SSH 返回信息,如SSH-1.99..
sudo tcpdump -i eth0 '(tcp[(tcp[12]>>2):4] = 0x5353482D) and (tcp[((tcp[12]>>2)+4):2]=0x312E)'
2.4 捕获 DNS 包
sudo tcpdump -i eth0 udp dst port 53
3. 传输层数据包(实用)
3.1 捕获 8080 端口 tcp 协议所有数据包
sudo tcpdump -i eth0 -s 0 tcp port 8080 -w /tmp/tcpdump.cap
3.2 捕获从本机 8070 端口出和入的所有 “HT”开头或“PO”、“GE” 开头的数据包
sudo tcpdump -XvvennSs 0 -i eth0 '((tcp[20:2]=0x4745 or tcp[20:2]=0x4854 or tcp[20:2]=0x504f) or (port 8070))' -w /root/log.cap
- 注: 0x4745 为GET前两个字母GE, 0x4854 为HTTP前两个字母HT, 0x504f为POST前缀PO
3.3 按地址过滤
- 捕获所有经过 eth0 源地址或目的地址为 192.168.1.1 的所有数据包
sudo tcpdump -i eth0 host 192.168.1.1
- 过滤源地址
sudo tcpdump -i eth0 src host 192.168.1.1
- 过滤目的地址
sudo tcpdump -i eth0 dst host 192.168.1.1
3.4 按端口过滤
- 捕获经过 eth0 源端口或目的端口为 25 的所有数据包
sudo tcpdump -i eth0 port 25
- 过滤源端口
sudotcpdump -i eth0 src port 25
- 过滤目的端口
sudo tcpdump -i eth0 dst port 25
3.5 按网段过滤
sudo tcpdump -i eth0 net 192.168
sudo tcpdump -i eth0 src net 192.168
sudo tcpdump -i dst net 192.168
3.6 按协议过滤
sudo tcpdump -i eth0 arp
sudo tcpdump -i eth0 ip
sudo tcpdump -i eth0 tcp
sudo tcpdump -i eth0 udp
sudo tcpdump -i eth0 icmp
3.7 运算符
-
非运算:!、or、not(去掉双引号)
-
与运算:&&、and
-
或运算:||、or
-
捕获所有经过 eth0,目的地址是 192.168.1.254 或 192.168.1.200 端口是 80 的 TCP 数据
sudo tcpdump -i eth0 '((tcp) and (port 80) and ((dst host 192.168.1.254) or (dst host 192.168.1.200)))'
- 捕获所有经过 eth0,目标 MAC 地址是 00:01:02:03:04:05 的 ICMP 数据
sudo tcpdump -i eth0 '((icmp) and ((ether dst host 00:01:02:03:04:05)))'
- 捕获所有经过 eth0,目的网络是 192.168,但目的主机不是 192.168.1.200 的 TCP 数据
sudo tcpdump -i eth0 '((tcp) and ((dst net 192.168) and (not dst host 192.168.1.200)))'
- 只抓 SYN 包
sudo tcpdump -i eth0 'tcp[tcpflags] = tcp-syn'
- 抓 SYN, ACK
sudo tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0'
4. 说明
-
-c
参数对于运维人员来说也比较常用,因为流量比较大的服务器,靠人工 CTRL+C 还是抓的太多,于是可以用-c 参数指定抓多少个包。 -
以下命令计算抓 10000 个 SYN 包花费多少时间,可以判断访问量大概是多少
sudo time tcpdump -nn -i eth0 'tcp[tcpflags] = tcp-syn' -c 10000 > /dev/null
- 实时捕获端口号8000的GET包,然后写入GET.log
sudo tcpdump -i eth0 '((port 8000) and (tcp[(tcp[12]>>2):4]=0x47455420))' -nnAl -w /tmp/GET.log
5. 参考
6. FAQ
6.1 如何在 TCPdump 中显示 MAC 地址
-
增加选项
-e
显示 MAC 地址,如:
sudo tcpdump -i any dst port 8080 or src port 8080 -e