3. tcpdump 核心用法:从安装到实战抓 HTTP

抓包分析这行当,tcpdump 是绕不过去的工具。说实话,我见过不少新人一上来就装 Wireshark,觉得图形界面友好。但等你到了生产环境,没图形界面、没鼠标、甚至带宽都快被撑爆的时候,tcpdump 才是你的救命稻草。今天我就带你把这把瑞士军刀玩明白。

本章核心目标:学会 tcpdump 的安装、基础语法、5 个最常用参数,并能独立抓取 HTTP 请求包。

3.1 安装 tcpdump

不同系统安装方式略有差异,但都很简单。我个人习惯在 Linux 服务器上直接用包管理器搞定。

系统 安装命令
Ubuntu / Debian sudo apt-get install tcpdump
CentOS / RHEL sudo yum install tcpdump
macOS brew install tcpdump(系统自带旧版)
Windows 安装 WinPcap 或 Npcap,再配合 Wireshark 自带

小提示:安装完后先跑一下 tcpdump --version 确认版本。我遇到过 CentOS 6 上默认装的是 3.x 老版本,有些参数行为不一样,建议升级到 4.x 以上。

3.2 基础语法

tcpdump 的语法其实就一句话:

tcpdump [参数] [表达式]

参数控制「怎么抓」,表达式控制「抓什么」。你想想看,这就像钓鱼——参数决定你用多粗的线、多大的钩,表达式决定你在哪个水域下竿。

一个最基础的抓包命令长这样:

sudo tcpdump -i eth0

这表示监听 eth0 网卡上的所有流量。嗯,这里要注意:不加任何过滤条件的话,你会被海量数据淹没。我刚开始学的时候就这么干过,结果终端刷屏刷到怀疑人生。

3.3 五大常用参数详解

tcpdump 参数很多,但真正高频使用的就 5 个。我把它们列出来,每个都说说我的使用心得。

参数 作用 示例
-i 指定监听的网卡接口 -i eth0、-i any
-n 不解析域名,直接显示 IP -n 避免 DNS 查询拖慢抓包
-X 以十六进制和 ASCII 显示包内容 -X 看应用层数据
-w 将抓到的包写入文件 -w capture.pcap
-r 从文件读取包进行分析 -r capture.pcap

3.3.1 -i:选对网卡

首先你得知道机器上有哪些网卡。用 tcpdump -D 可以列出所有可用接口。

$ tcpdump -D
1.eth0 [Up, Running]
2.lo [Up, Running, Loopback]
3.any (Pseudo-device that captures on all interfaces)

我个人习惯用 -i any 来抓所有接口的流量,省得来回切换。但要注意,any 接口在某些模式下(比如混杂模式)行为略有不同,生产环境建议指定具体网卡。

3.3.2 -n:别让 DNS 拖后腿

这个参数我几乎每次都加。为什么?因为 tcpdump 默认会做反向 DNS 查询,把 IP 解析成域名。这在网络不通或 DNS 慢的时候,会让抓包变得奇慢无比。

我曾经在排查一个 DNS 故障时,忘了加 -n,结果 tcpdump 自己卡在 DNS 查询上,包都抓不全。从那以后,-n 就成了我的肌肉记忆。

# 不加 -n,tcpdump 会尝试解析域名
sudo tcpdump -i eth0

# 加 -n,直接显示 IP,速度快 10 倍
sudo tcpdump -i eth0 -n

3.3.3 -X:看穿包的内容

-X 参数会同时显示十六进制和 ASCII 内容。这对分析应用层协议特别有用,比如 HTTP 的请求头和响应体。

sudo tcpdump -i eth0 -n -X port 80

输出大概长这样:

0x0000:  4500 0054 3a2b 4000 4006 1c3c 0a00 0002  E..T:+@.@..<....
0x0010:  0a00 0001 0050 9a7b 0000 0000 0000 0000  .....P.{........
0x0020:  5002 2000 3f3f 0000 4745 5420 2f20 4854  P..??..GET./.HT
0x0030:  5450 2f31 2e31 0d0a 486f 7374 3a20 7777  TP/1.1..Host:.ww
0x0040:  772e 6578 616d 706c 652e 636f 6d0d 0a0d  w.example.com...
0x0050:  0a                                       .

看到右边那列了吗?GET / HTTP/1.1 和 Host: www.example.com 清清楚楚。这就是 HTTP 请求的原始内容。

注意:-X 会输出大量数据,如果流量很大,建议先保存到文件再用 -r 分析,否则终端会刷爆。

3.3.4 -w 和 -r:保存与回放

这两个参数是黄金搭档。-w 把包存成 pcap 文件,-r 读回来分析。

# 抓包并保存
sudo tcpdump -i eth0 -n -w http_capture.pcap port 80

# 事后分析
tcpdump -r http_capture.pcap -n -X

为什么推荐先保存再分析?原因有三:

  • 不影响现场:抓包时 CPU 和内存开销最小化
  • 反复分析:同一个包可以用不同参数看多次
  • 分享协作:把 pcap 发给同事,大家用 Wireshark 一起看

我记得有一次线上故障,我现场抓了 5 分钟的包,保存下来后慢慢分析,最终定位到一个第三方 SDK 发了异常大的请求体。如果当时直接终端看,根本来不及反应。

3.4 实战:抓取 HTTP 包

理论讲完了,咱们直接上手。下面是一个完整的 HTTP 抓包实战流程。

3.4.1 场景描述

假设我们要抓取本机访问 http://example.com 的 HTTP 请求和响应。目标:看到完整的请求头和响应头。

3.4.2 步骤一:启动抓包

sudo tcpdump -i eth0 -n -X -w http_demo.pcap port 80 or port 443

这里我加了 port 80 or port 443,只抓 HTTP 和 HTTPS 流量。HTTPS 虽然内容加密,但握手过程和 IP 信息还是有分析价值的。

3.4.3 步骤二:发起请求

另开一个终端,用 curl 模拟请求:

curl http://example.com

3.4.4 步骤三:停止抓包

按 Ctrl+C 停止 tcpdump。你会看到类似这样的统计:

9 packets captured
18 packets received by filter
0 packets dropped by kernel

注意看 packets dropped by kernel,如果这个数字很大,说明你的抓包缓冲区不够,需要加 -B 参数调大。

3.4.5 步骤四:分析结果

tcpdump -r http_demo.pcap -n -X

你会看到类似这样的输出:

13:45:22.123456 IP 192.168.1.100.54321 > 93.184.216.34.80: Flags [S], seq 1234567890, ...
13:45:22.123789 IP 93.184.216.34.80 > 192.168.1.100.54321: Flags [S.], seq 987654321, ...
13:45:22.124012 IP 192.168.1.100.54321 > 93.184.216.34.80: Flags [.], ack 1, ...
13:45:22.124256 IP 192.168.1.100.54321 > 93.184.216.34.80: Flags [P.], seq 1:78, ack 1, ...
  0x0000:  4745 5420 2f20 4854 5450 2f31 2e31 0d0a  GET./.HTTP/1.1..
  0x0010:  486f 7374 3a20 6578 616d 706c 652e 636f  Host:.example.co
  0x0020:  6d0d 0a55 7365 722d 4167 656e 743a 2063  m..User-Agent:.c
  0x0030:  7572 6c2f 372e 3638 2e30 0d0a 4163 6365  url/7.68.0..Acce
  0x0040:  7074 3a20 2a2f 2a0d 0a0d 0a              pt:.*/*....

看懂了吗?前三行是 TCP 三次握手,第四行开始才是 HTTP 请求内容。右边 ASCII 区能看到完整的 GET / HTTP/1.1 和请求头。

实战技巧:如果只想看 HTTP 请求行和响应行,可以用 -A 参数只显示 ASCII 内容,比 -X 更清爽。

3.5 本章知识体系

下面这张图帮你梳理 tcpdump 的核心脉络:

tcpdump 核心用法知识体系 tcpdump 核心用法知识体系 tcpdump 核心用法 ① 安装 ② 基础语法 ③ 实战抓 HTTP apt / yum / brew 验证版本:--version tcpdump [参数] [表达式] 参数控制「怎么抓」,表达式控制「抓什么」 启动 → 请求 → 停止 → 分析 -w 保存 + -r 回放 五大核心参数:-i -n -X -w -r -i 指定网卡 -n 不解析域名 -X Hex + ASCII -w 写入文件 -r 读取文件 💡 核心原则:先保存(-w)再分析(-r),避免现场数据丢失

3.6 避坑指南

最后分享几个我踩过的坑,你遇到了能少走弯路。

坑一:权限不足

tcpdump 需要 root 权限才能抓包。如果你忘了加 sudo,会报错 permission denied。我刚开始用的时候经常犯这个错,后来直接 alias 了一个 sudo tcpdump 的快捷命令。

坑二:缓冲区溢出

在高流量环境下,tcpdump 默认缓冲区可能不够,导致丢包。你会看到 packets dropped by kernel 不为 0。解决办法是加 -B 4096 把缓冲区设到 4MB。

坑三:表达式写错

tcpdump 的表达式语法比较严格。比如 port 80 and host 192.168.1.1 和 port 80 && host 192.168.1.1 是等价的,但 and 和 && 不能混用。我建议统一用 and、or、not,可读性更好。

好了,tcpdump 的核心用法就这些。记住五个参数:-i 选网卡、-n 禁 DNS、-X 看内容、-w 存文件、-r 读文件。配合端口过滤,抓 HTTP 包就是分分钟的事。