前言
Wireshark虽然好用,但服务器上通常没有图形界面。tcpdump是Linux下最常用的命令行抓包工具,排查网络问题、分析协议、定位连接异常都离不开它。
本文整理tcpdump的常用技巧,从基础语法到实际问题排查,配合真实场景案例。
1. 基础用法
1.1 最简单的抓包
# 抓取eth0网卡的所有流量tcpdump-ieth0# 抓取所有网卡tcpdump-iany# 指定抓取数量tcpdump-ieth0-c1001.2 常用参数
# -n:不解析主机名(速度快)# -nn:不解析主机名和端口名tcpdump-ieth0-nn# -v/-vv/-vvv:详细程度递增tcpdump-ieth0-vv# -X:同时以十六进制和ASCII显示包内容tcpdump-ieth0-X# -A:以ASCII显示包内容(适合HTTP)tcpdump-ieth0-A# -s0:抓取完整数据包(默认只抓前96字节)tcpdump-ieth0-s0# -w:保存到文件(可用Wireshark打开)tcpdump-ieth0-wcapture.pcap# -r:读取抓包文件tcpdump-rcapture.pcap1.3 组合使用
# 常用组合:不解析、完整包、保存文件tcpdump-ieth0-nn-s0-w/tmp/capture.pcap# 边抓边看,同时保存tcpdump-ieth0-nn-U-w/tmp/capture.pcap&tail-f/tmp/capture.pcap|tcpdump-r-2. 过滤表达式
tcpdump强大之处在于过滤表达式,精准抓取需要的流量。
2.1 按主机过滤
# 抓取与192.168.1.100通信的所有流量tcpdump-ieth0host192.168.1.100# 抓取源地址为192.168.1.100tcpdump-ieth0 srchost192.168.1.100# 抓取目标地址为192.168.1.100tcpdump-ieth0 dsthost192.168.1.100# 抓取与多个主机通信tcpdump-ieth0host192.168.1.100 orhost192.168.1.101# 排除某个主机tcpdump-ieth0 nothost192.168.1.1002.2 按端口过滤
# 抓取80端口流量tcpdump-ieth0 port80# 抓取源端口为80tcpdump-ieth0 src port80# 抓取目标端口为80tcpdump-ieth0 dst port80# 抓取端口范围tcpdump-ieth0 portrange8000-9000# 抓取多个端口tcpdump-ieth0 port80or port443or port80802.3 按协议过滤
# 只抓TCPtcpdump-ieth0 tcp# 只抓UDPtcpdump-ieth0 udp# 只抓ICMP(ping)tcpdump-ieth0 icmp# 只抓ARPtcpdump-ieth0 arp2.4 按网段过滤
# 抓取192.168.1.0/24网段tcpdump-ieth0 net192.168.1.0/24# 抓取源网段tcpdump-ieth0 src net10.0.0.0/82.5 按TCP标志位过滤
# 抓取SYN包(新连接)tcpdump-ieth0'tcp[tcpflags] & tcp-syn != 0'# 抓取SYN+ACK包tcpdump-ieth0'tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)'# 抓取FIN包(连接关闭)tcpdump-ieth0'tcp[tcpflags] & tcp-fin != 0'# 抓取RST包(连接重置)tcpdump-ieth0'tcp[tcpflags] & tcp-rst != 0'# 简写方式tcpdump-ieth0'tcp[13] & 2 != 0'# SYNtcpdump-ieth0'tcp[13] & 1 != 0'# FINtcpdump-ieth0'tcp[13] & 4 != 0'# RST2.6 组合过滤
# 抓取到MySQL的流量tcpdump-ieth0 dst port3306and dsthost192.168.1.100# 抓取HTTP请求(排除SSH)tcpdump-ieth0 port80and not port22# 抓取指定IP的TCP SYN包tcpdump-ieth0'host 192.168.1.100 and tcp[tcpflags] & tcp-syn != 0'# 复杂组合:抓取从web服务器到数据库的非SSH流量tcpdump-ieth0'src host 192.168.1.10 and dst host 192.168.1.20 and not port 22'3. 输出解读
3.1 TCP包格式
14:22:31.123456 IP 192.168.1.10.45678 > 192.168.1.20.80: Flags [S], seq 123456, win 64240, length 0各部分含义:
14:22:31.123456:时间戳192.168.1.10.45678:源IP.端口192.168.1.20.80:目标IP.端口Flags [S]:TCP标志位seq 123456:序列号win 64240:窗口大小length 0:数据长度
3.2 TCP标志位
| 标志 | 含义 |
|---|---|
| S | SYN,发起连接 |
| . | ACK,确认 |
| F | FIN,关闭连接 |
| R | RST,重置连接 |
| P | PSH,推送数据 |
| S. | SYN+ACK |
| F. | FIN+ACK |
3.3 三次握手示例
# 客户端发SYN14:22:31.001 IP10.0.0.1.45678>10.0.0.2.80: Flags[S],seq100# 服务端回SYN+ACK14:22:31.002 IP10.0.0.2.80>10.0.0.1.45678: Flags[S.],seq200, ack101# 客户端发ACK14:22:31.003 IP10.0.0.1.45678>10.0.0.2.80: Flags[.], ack2014. 实战场景
4.1 排查连接超时
服务调用超时,先确认是不是网络层面的问题。
# 抓取到目标服务的SYN包tcpdump-ieth0-nn'dst host 192.168.1.100 and dst port 8080 and tcp[tcpflags] & tcp-syn != 0'如果看到大量SYN但没有SYN+ACK,说明:
- 对端服务没起来
- 防火墙拦截了
- 网络不通
# 同时看SYN和SYN+ACKtcpdump-ieth0-nn'host 192.168.1.100 and port 8080 and (tcp[tcpflags] & tcp-syn != 0)'4.2 排查连接被重置
如果连接频繁被RST,抓包分析原因。
# 抓取RST包tcpdump-ieth0-nn'tcp[tcpflags] & tcp-rst != 0'常见原因:
- 端口没监听
- 连接数超限
- 防火墙策略
- 应用主动关闭
4.3 分析HTTP请求
# 抓取HTTP请求行tcpdump-ieth0-A-s0'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'# 简单版本tcpdump-ieth0-Aport80|grep-E'GET|POST|HTTP'4.4 抓取DNS查询
# 抓取所有DNS流量tcpdump-ieth0-nnport53# 只看DNS查询内容tcpdump-ieth0-nn-vport53输出示例:
14:22:31.123 IP 192.168.1.10.54321 > 8.8.8.8.53: 12345+ A? www.example.com. (33) 14:22:31.145 IP 8.8.8.8.53 > 192.168.1.10.54321: 12345 1/0/0 A 93.184.216.34 (49)4.5 分析数据库连接
# MySQL连接问题排查tcpdump-ieth0-nnport3306# 看MySQL协议内容tcpdump-ieth0-Xport3306|grep-A5'Error'# Redis连接tcpdump-ieth0-nnport6379-A4.6 排查网络丢包
抓取重传包:
# 抓取TCP重传(通过序列号判断)# 方法:保存抓包文件,用tshark分析tcpdump-ieth0-nn-w/tmp/capture.pcap tshark-r/tmp/capture.pcap-Y"tcp.analysis.retransmission"或者简单判断:
# 看有没有大量重复的seqtcpdump-ieth0-nn'tcp'|awk'{print $1,$2,$3,$4,$5}'|sort|uniq-c|sort-rn|head5. 高级技巧
5.1 抓包文件轮转
长时间抓包,防止文件过大:
# 每100MB切一个文件,最多保留10个tcpdump-ieth0-w/tmp/capture.pcap-C100-W10# 每小时切一个文件tcpdump-ieth0-w/tmp/capture_%Y%m%d_%H%M%S.pcap-G36005.2 远程抓包本地分析
服务器上抓包,传到本地用Wireshark分析:
# 方法1:抓完传输tcpdump-ieth0-w/tmp/capture.pcapscpserver:/tmp/capture.pcap.# 方法2:实时传输(需要网络稳定)sshuser@server'tcpdump -i eth0 -w - port 80'|wireshark-k-i-# 方法3:通过管道sshuser@server'tcpdump -i eth0 -nn -U -w - port 80'>capture.pcap5.3 多节点同时抓包
排查分布式系统问题,经常需要在多台机器同时抓包。
手动方式:
# 在多台机器上同时执行,用时间戳对齐tcpdump-ieth0-nn-tt-w/tmp/capture_$(hostname).pcap'port 8080'批量方式(用Ansible):
# capture.yml-hosts:alltasks:-name:开始抓包shell:|nohup tcpdump -i eth0 -nn -w /tmp/capture_{{ inventory_hostname }}.pcap \ 'port 8080' &async:60poll:0如果机器在不同网络环境,逐个SSH登录很麻烦。我一般会用组网工具(WireGuard、ZeroTier、星空组网这类)先把机器串到一个虚拟网络,然后Ansible批量执行。
5.4 抓取指定进程的流量
tcpdump本身不支持按进程过滤,但可以曲线救国:
# 1. 找到进程监听的端口ss-tlnp|grepnginx# 2. 按端口抓包tcpdump-ieth0 port80or port443# 或者用strace跟踪进程的网络调用strace-f-etrace=network-p$(pgrep nginx)5.5 抓取特定内容的包
# 抓取包含"error"的HTTP响应tcpdump-ieth0-Aport80|grep-ierror# 抓取包含特定字符串的包tcpdump-ieth0-s0-A|grep-B5-A5'password'# 使用ngrep(更专业的内容过滤)ngrep-deth0'GET'port806. 常用抓包命令速查
# 抓取到某服务的所有连接tcpdump-ieth0-nnhost192.168.1.100 and port8080# 抓取新建连接tcpdump-ieth0-nn'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'# 抓取连接关闭tcpdump-ieth0-nn'tcp[tcpflags] & (tcp-fin|tcp-rst) != 0'# 抓取大于1000字节的包tcpdump-ieth0-nn'greater 1000'# 抓取HTTPS握手(Client Hello)tcpdump-ieth0-nn'tcp port 443 and (tcp[((tcp[12] & 0xf0) >> 2)] = 0x16)'# 抓取ICMP错误包tcpdump-ieth0-nn'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply'# 排除干扰流量tcpdump-ieth0-nn'not port 22 and not arp and not port 53'7. 性能注意事项
7.1 避免影响生产
# 限制抓包速率tcpdump-ieth0-c10000# 只抓10000个包# 只抓包头,不抓内容tcpdump-ieth0-s96# 默认值,够分析协议了# 用BPF过滤减少内核到用户态的数据量tcpdump-ieth0'port 80'# 比抓全部再grep好7.2 高流量场景
# 增加buffer防止丢包tcpdump-ieth0-B4096-wcapture.pcap# 用pfring等高性能抓包工具# 或者直接用tc做流量镜像到分析机总结
| 场景 | 命令 |
|---|---|
| 基础抓包 | tcpdump -i eth0 -nn |
| 抓特定主机 | tcpdump -i eth0 host 192.168.1.100 |
| 抓特定端口 | tcpdump -i eth0 port 80 |
| 抓TCP连接建立 | tcpdump 'tcp[tcpflags] & tcp-syn != 0' |
| 抓RST包 | tcpdump 'tcp[tcpflags] & tcp-rst != 0' |
| 保存到文件 | tcpdump -w capture.pcap |
| 看HTTP内容 | tcpdump -A port 80 |
| 抓DNS | tcpdump -nn port 53 |
排查思路:
- 先明确要抓什么流量,构造过滤表达式
- 抓包同时复现问题
- 用Wireshark或tshark分析抓包文件
- 对比正常和异常时的包,找出差异
tcpdump配合Wireshark,基本能搞定大部分网络问题排查。