当你在服务器上遇到接口超时、连接被拒或偶发丢包,而应用日志却一团和气时,tcpdump 就是你的第一把手术刀。作为最经典的命令行抓包工具,tcpdump 能在无图形界面的生产环境直接捕获网卡流量,把”网络故障”从玄学猜测变成可视证据。本文从基础语法讲到三个真实排查场景,帮你用抓包快速定位问题。
一、tcpdump 能解决哪类网络故障
很多”网络问题”其实根本不在网络层,而在应用层或配置层。tcpdump 的价值在于用数据包本身说话,尤其在以下场景不可替代:
- 接口偶发超时,但服务端日志显示请求根本没进来——抓包能确认包到底到没到。
- TCP 连接能建立但很快被 RST 断开,需要看是谁先发的断开标志。
- 怀疑有异常出站流量或扫描行为,需要看实际发出去的包。
- Nginx、Docker 网络、DNS 等组件的边界问题,用抓包确认流量走向。
它和 Wireshark 图形化抓包 是互补关系:Wireshark 适合在本地分析,而 tcpdump 胜在服务器上”随手就能跑”,尤其当机器没有图形界面、也不方便把流量导出来时。
二、基础语法与权限
tcpdump 需要读取网卡,通常以 root 或具备 CAP_NET_RAW 权限的用户运行。最基本的命令是监听某个网卡并打印摘要:
# 监听所有网卡, numeric 输出(不反向解析主机名),显示详细信息
sudo tcpdump -i any -n -v
# 只看 eth0,且不显示链路层头,输出更紧凑
sudo tcpdump -i eth0 -n -t
# 限制抓取 100 个包后自动退出,避免刷屏
sudo tcpdump -i any -n -c 100
常用参数速记:-i 指定网卡(any 表示全部),-n 不解析域名、-nn 连端口号也不解析成服务名(更快更干净),-v/-vv 提高冗余度,-c 限制包数,-w 写入文件。
一个高频踩坑:明明有流量却”抓不到回包”。通常不是 tcpdump 坏了,而是抓错了网卡——容器里的服务流量走 docker0 或 veth 虚拟网卡,直接抓 eth0 自然看不到;用 -i any 或先 ip addr 确认发包网卡最稳妥。另外,若本机发出的包被网卡开启了 GRO/GSO 卸载而合并,抓包可能看到异常的”超大帧”,属正常现象,不影响分析。
三、过滤表达式:精准抓你想要的包
生产环境流量巨大,不加过滤会瞬间淹没终端。tcpdump 的过滤表达式(BPF)是它的精髓,按”原语”组合即可:
| 原语 | 含义 | 示例 |
|---|---|---|
host | 匹配源或目的 IP/主机 | host 10.0.0.5 |
src / dst | 限定方向 | dst host 10.0.0.5 |
port | 匹配端口 | port 8080 |
net | 匹配网段 | net 192.168.1.0/24 |
tcp / udp / icmp | 匹配协议 | tcp |
and / or / not | 逻辑组合 | host 10.0.0.5 and port 8080 |
例如只关心发往 8080 端口、且来自特定客户端的 TCP 包:
sudo tcpdump -i eth0 -nn 'host 10.0.0.5 and tcp port 8080'
四、实战一:定位接口连接超时(看三次握手)
最经典的故障:客户端连某个服务一直超时。先抓两端之间的包,重点看 TCP 三次握手是否完成:
# 抓取与目标主机之间的 TCP 握手与断开标志
sudo tcpdump -i eth0 -nn 'host 10.0.0.5 and tcp port 8080 and tcp[tcpflags] & (tcp-syn|tcp-ack|tcp-rst) != 0'
正常情况应看到 SYN → SYN,ACK → ACK 三行。如果只看到客户端发出的 SYN 却没有任何回应,说明包到了服务器但没进程监听该端口,或中间防火墙把包丢了——这时要去查对端服务是否真的在监听(ss -lntp),以及安全组/iptables 规则。若看到 SYN 后有 RST 立即回包,通常是端口无服务或连接被主动拒绝。
这类”包到了但应用没反应”的问题,也常和反向代理层有关,可以参考 Nginx 反向代理完整配置 排查 upstream 是否真正可达。
五、实战二:排查丢包与重传
接口偶发卡顿、响应慢,往往是 TCP 重传在作祟。抓包时关注 RST 和重传:
# 抓取所有 RST 和 SYN 包,快速发现异常断开
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-rst|tcp-syn) != 0'
# 抓取重传(TCP 序号重复出现通常意味着丢包)
sudo tcpdump -i eth0 -nn 'host 10.0.0.5 and (tcp[tcpflags] & tcp-ack != 0)' -v
如果抓包里频繁出现同一序号的重复 ACK 或重传,基本可以判定链路存在丢包,可能是网卡、交换机、云厂商限速或 MTU 不匹配。此时结合 ifconfig 看 RX/TX errors、dropped 计数,以及 mtr 逐跳观察,能进一步收敛根因。确认重传最直观的办法是加 -v 看每段的 seq 与 ack 序号:正常交互里确认号稳步递增,一旦发现某个 seq 被重复发送、且伴随 DUP ACK,就是接收方没收到、发送方在补发,丢包坐实。
六、实战三:揪出异常出站流量
怀疑服务器被植入挖矿或扫描程序时,可以反向抓”不该出去的包”。比如只允许内网通信,却看到大量发往外网的连接:
# 抓所有"目的地不在内网 10.0.0.0/8"的出站 TCP 包
sudo tcpdump -i eth0 -nn 'dst net not 10.0.0.0/8 and tcp'
通过分析这些包的目的 IP 和端口,往往能直接定位到可疑进程(再用 netstat -antp 或 ss -antp 反查 PID)。在容器化环境里,异常流量有时来自某个容器,可结合 Docker Compose 网络模式 理解容器间通信边界。
七、把抓包存下来用 Wireshark 深分析
终端里看摘要不够时,用 -w 存成 pcap 文件,下载到本地用 Wireshark 打开,能看明文协议、TLS 握手、HTTP 内容等:
# 抓取 60 秒后自动停止,写入文件(生产环境避免无限抓包占满磁盘)
sudo tcpdump -i eth0 -nn -G 60 -W 1 -w /tmp/capture_%Y%m%d_%H%M.pcap 'host 10.0.0.5 and port 8080'
# 边抓边用 gzip 压缩,节省空间
sudo tcpdump -i eth0 -nn -w - 'port 443' | gzip > /tmp/cap.pcap.gz
-G 60 -W 1 表示每 60 秒滚动一次、最多保留 1 个文件,是生产环境防磁盘写爆的标配。抓完后用 scp 拉回本地即可。
八、常见坑与排障清单
| 现象 | 可能原因 | 抓包验证要点 |
|---|---|---|
| 客户端超时无响应 | 服务未监听 / 防火墙丢弃 | 只看到 SYN,无 SYN,ACK |
| 连接秒断 | 端口无服务 / 主动 RST | SYN 之后紧跟 RST |
| 响应慢、卡顿 | 链路丢包 / 重传 | 重复 ACK、重传序号 |
| 能 ping 通但端口不通 | 安全组/iptables 限制 | ICMP 通但 TCP SYN 无回 |
| 容器间不通 | Docker 网络/网段冲突 | 跨网桥无对应 MAC 转发 |
抓包排查奉行的原则很简单:先确认包到没到,再确认包对不对,最后看是谁先动手断开。有了 tcpdump 这把刀,绝大多数”网络玄学”都能在几分钟内现出原形。如果问题出在域名解析阶段而非 TCP 传输,可以进一步参考 DNS 解析故障排查实战;若是 TCP 连接数打满导致的端口耗尽,可看 TIME_WAIT 过多排查实战 对症下药。




