第3章:tcpdump 命令行抓包——Linux 下必会的抓包工具

说到抓包,很多新手第一反应是 Wireshark。但在服务器、嵌入式、或者没有图形界面的环境里,tcpdump 才是真正的王者。我最早接触它是在一次线上服务延迟排查中,没法装图形工具,全靠 tcpdump 拉流量分析。嗯,从那以后我就把它当成随身“听诊器”了。

这一章我们直接上手 tcpdump,从常用选项到过滤表达式,再到保存 pcap 文件,把抓包基础打扎实。别看它命令行黑乎乎,用熟了比 Wireshark 还顺手。

3.1 基本用法与常用选项

tcpdump 的语法很简单:tcpdump [选项] [过滤表达式]。不加任何选项,默认抓第一个网卡的所有包。但这样会刷屏,我们得学会控制。

选项作用我的常用场景
-i eth0指定抓取 eth0 网卡多网卡机器选接口
-n不解析域名,只显示 IP避免 DNS 延迟,抓包更快
-nn不解析域名+不解析端口名我排查时必加,少干扰
-c 100抓 100 个包后自动停止测试场景,防止刷屏
-s 0抓完整包(默认 262144 字节)分析 payload 时用
-w file.pcap保存成 pcap 文件保留证据,后续分析
-r file.pcap读取 pcap 文件离线分析或分享抓包
-v / -vv / -vvv增加输出详细度查协议细节时用 -vv

个人习惯组合:tcpdump -i any -nn -c 100 -s 0。any 可以抓所有接口流量,-nn 避免 DNS 干扰,-c 控制包量。我调试时经常先跑这个组合看看大局。

避坑提醒:我曾经在抓大流量时忘了加 -c,结果终端刷了几十万行卡死,不得不强杀进程。所以非永久监听一定要加 -c 或 -G 轮转保存。

3.2 捕获过滤表达式——BPF 语法

tcpdump 最强大的地方是它的过滤能力,底层用的是 Berkeley Packet Filter(BPF)。说白了就是写一个“条件”,让内核只把符合条件的包丢给用户态。效率极高。

表达式由原语(primitive)和连接词(and/or/not)组成。常用的原语按类型分:

类型示例含义
主机host 192.168.1.1匹配源或目标 IP 为 192.168.1.1
网络net 10.0.0.0/8匹配 10.x.x.x 网段
端口port 80匹配源或目标端口 80
协议tcp / udp / icmp只抓该协议包
方向src port 53只抓源端口 53(DNS 响应)

3.3 组合过滤:从简单到实战

单条原语不够用,得组合。比如我要抓从 192.168.1.100 发往 10.0.0.1 的 HTTP 请求:

tcpdump -i eth0 -nn tcp and host 192.168.1.100 and host 10.0.0.1 and port 80

其实可以简写成 tcp and src 192.168.1.100 and dst 10.0.0.1 and port 80。我个人更爱用 host 加方向,可读性好一点。你想想看,如果你只关心目标端口 443,可以用 dst port 443,少抓很多无关包。

注意:过滤表达式里不要乱加括号,tcpdump 对括号的转义很敏感。建议用单引号把整个表达式包起来,比如 tcpdump 'tcp and port 80',避免 shell 解释特殊字符。

3.4 保存 pcap 文件——把证据留下来

抓包最重要的目的是回放分析。tcpdump 保存 pcap 文件的命令是:

tcpdump -i eth0 -nn -s 0 -w capture.pcap port 443

这会生成一个标准 pcap 文件,可以用 Wireshark、tshark 或者 tcpdump 自己打开:

tcpdump -r capture.pcap -nn

保存时我建议:

  • 始终加 -s 0 抓完整包,否则裁剪后的包无法分析应用层数据。
  • 使用 -C 100 让文件到达 100MB 后自动轮转,避免单文件过大。
  • 配合 -W 10 限制轮转文件总数,防止磁盘写爆。

举个例子,监控 DNS 流量,每 100MB 轮转,最多保留 5 个文件:

tcpdump -i eth0 -nn -s 0 -C 100 -W 5 -w dns_trace.pcap port 53

这是我线上常用的一招。有一次排查 DNS 解析慢,直接这样抓了 10 分钟,然后拉下来用 Wireshark 看响应时间分布,一目了然。

3.5 本章知识体系

tcpdump 抓包核心逻辑 网卡/接口 主要选项 -i / -n / -c / -s -w / -r / -v 过滤表达式 host / port / net and / or / not 保存与回放 -w file.pcap -r file.pcap 标准输出 / pcap 文件 提示:先选接口 → 搭配选项 → 写过滤表达式 → 决定实时看还是存文件

3.6 实战小案例:抓一次 HTTP 请求的完整流程

假设你想看看 wget 请求 www.example.com 时到底发了什么包。可以这样:

  1. 先确定接口:ip addr 看哪个网卡有流量。
  2. 写过滤表达式:抓目标端口 80,并且只抓与目标 IP 相关的包(先 ping 一下得到 IP)。
  3. 保存 pcap,不刷屏:
tcpdump -i eth0 -nn -s 0 -c 20 -w http_test.pcap host 93.184.216.34 and port 80
  1. 在另一个终端执行 wget http://www.example.com。
  2. 抓完 20 个包后 tcpdump 自动退出,查看文件:
tcpdump -r http_test.pcap -nn -vv

你会看到三次握手、HTTP GET 请求、响应以及挥手。我用这个案例教过入门同事,他们都说比看文档好理解多了。

小技巧:如果想看 HTTP 协议内容,可以加 -A 参数以 ASCII 格式打印包 payload,或者保存后用 Wireshark 的“Follow TCP Stream”功能。我个人偏爱后者,因为可读性更好。

3.7 常见错误与排查

现象原因解决办法
抓了几万个包什么都没看到过滤表达式写错了先不加表达式跑一次确认接口有流量
保存的 pcap 在 Wireshark 里打不开tcpdump 版本低,格式不兼容用 file 命令查看真实格式,升级 tcpdump
“Permission denied”普通用户无权限加 sudo 或者赋予 CAP_NET_RAW 能力
抓包文件太大导致磁盘满没加 -c 或 -C 轮转生产环境必须加轮转参数,配合监控报警

我记得有一次同事在线上服务器抓包,忘了加 -c,又没进 root 用户,结果权限报错后还被领导批评。从那以后我的抓包脚本都会写一行检查权限的提示。


tcpdump 的命令行艺术就在这几个选项和表达式的组合里。你多练几次,形成自己的“组合拳”,以后遇到网络问题,手指自然就敲出来了。