tcpdump 命令详解与参数实测(Ubuntu 22.04)

在 Ubuntu 22.04 实测 tcpdump 常用参数:-i 接口选择、-n/-nn、-c、-w/-r、-A/-X/-s、host/net/port/src/dst 与 and/or/not 过滤、-v、-t、-l、-G/-W 轮转、-e 二层头,逐列解读回显与 TCP Flags,附 BPF 语法速查、-G 轮转降权限坑与 HTTP/DNS 实战,全部命令真实执行并记录回显。

Linux命令Linux系统UbuntuUbuntu 22.04命令行网络工具2026/10/16

tcpdump 命令详解与参数实测(Ubuntu 22.04)

一、环境信息

本文所有命令均在以下真实服务器环境中逐条执行并记录回显,读者可按相同条件复现:

  • 操作系统:Ubuntu 22.04.5 LTS(PRETTY_NAME="Ubuntu 22.04.5 LTS"),架构 x86_64,root 用户执行;
  • tcpdump 版本:tcpdump version 4.99.1,libpcap version 1.10.1 (with TPACKET_V3),OpenSSL 3.0.2 15 Mar 2022(软件包版本 4.99.1-3ubuntu0.2);
  • 网络接口:eth0(第一块网卡),本机地址 172.17.0.2/16,默认网关 172.17.0.1;DNS 服务器 192.168.146.2(内网解析,正反向均可用);
  • 出口链路:经 NAT 访问公网,223.5.5.5(阿里云公共 DNS,反向解析名 public1.alidns.com)可达,RTT 约 21ms;
  • 本地演示固定装置:python3 -m http.server 18080 提供 HTTP 明文服务,站点根目录 /root/demo/tcpdump/www,页面 /index.html;实测时间以服务器时钟为准(回显时间戳为 2026-10-15 20 时段)。

⚠️ 说明:抓包需要 CAP_NET_RAW 原始套接字能力,本文以 root 执行。tcpdump 启动后会自动降权为 tcpdump 用户运行(-Z 默认行为),这一特性会在 -w/-G 小节产生真实影响(输出文件属主与轮转权限),详见 3.6 与 3.18 节。

二、命令概览

2.1 安装

tcpdump 在 Ubuntu Server 默认安装中通常已预装;未安装时通过 apt 安装即可。本机与 traceroute 同批重装(traceroute 详见同系列文档),安装命令与回显节选如下:

$ DEBIAN_FRONTEND=noninteractive apt-get install -y -qq traceroute tcpdump
Setting up tcpdump (4.99.1-3ubuntu0.2) ...
Setting up traceroute (1:2.1.0-2) ...

安装后位于 /usr/bin/tcpdump(软件包版本 4.99.1-3ubuntu0.2)。

2.2 语法与测试数据

tcpdump 的命令语法(取自 --help 原文):

Usage: tcpdump [-AbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ] [--count]
		[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
		[ -i interface ] [ --immediate-mode ] [ -j tstamptype ]
		[ -M secret ] [ --number ] [ --print ] [ -Q in|out|inout ]
		[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]
		[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]
		[ --time-stamp-precision precision ] [ --micro ] [ --nano ]
		[ -z postrotate-command ] [ -Z user ] [ expression ]

两部分构成:选项(-i/-nn/-c/-w 等)控制「怎么抓、抓到哪」,过滤表达式(BPF 语法,写在命令末尾)控制「抓什么」——内核态先行过滤,只有匹配的包才送入用户态。本文测试数据约定:造流量目标 223.5.5.5(ping 测 ICMP、curl -sk https://223.5.5.5 测 TCP 443);本地 HTTP 固定装置 python3 -m http.server 18080 --directory /root/demo/tcpdump/www,页面 <h1>tcpdump demo page</h1>(27 字节);DNS 造流量用 python3 -c "import socket; socket.getaddrinfo('www.baidu.com', 80, socket.AF_INET, socket.SOCK_STREAM)" 强制发起一次 A 记录查询(比 getent 更可控)。后台抓包与造流量配合的长命令按分号拆行展示(语义与实测一致),每行回显均逐字取自实测日志。

2.3 --help 全量输出(逐行照抄)

$ tcpdump --help; echo rc=$?
tcpdump version 4.99.1
libpcap version 1.10.1 (with TPACKET_V3)
OpenSSL 3.0.2 15 Mar 2022
Usage: tcpdump [-AbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ] [--count]
		[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
		[ -i interface ] [ --immediate-mode ] [ -j tstamptype ]
		[ -M secret ] [ --number ] [ --print ] [ -Q in|out|inout ]
		[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]
		[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]
		[ --time-stamp-precision precision ] [ --micro ] [ --nano ]
		[ -z postrotate-command ] [ -Z user ] [ expression ]
rc=0

注意:tcpdump 的 --help 只给出选项速记(不是每个选项的说明),完整选项解释要查手册页(第六节给出链接)。退出码实测 rc=0。

2.4 版本信息

$ tcpdump --version
tcpdump version 4.99.1
libpcap version 1.10.1 (with TPACKET_V3)
OpenSSL 3.0.2 15 Mar 2022

libpcap 是 tcpdump 的抓包库,排查「抓包异常/丢包」时两者版本都要关注。tcpdump -D 可列出本机全部可抓接口(实测 8 个:eth0、any、lo、bluetooth-monitor、nflog、nfqueue、dbus-system、dbus-session),编号最前的 eth0 即不指定 -i 时的默认接口。

2.5 抓包回显逐列解读与同类工具对比

以一条典型抓包行为例(来源见 3.1 节完整回显):

20:03:54.210794 IP f1034b9326b2.36366 > public1.alidns.com.https: Flags [S], seq 2770491245, win 64240, options [mss 1460,sackOK,TS val 3014965719 ecr 0,nop,wscale 7], length 0
  • 20:03:54.210794:抓到该包的时刻(默认 时:分:秒.微秒,可用 -t/-tttt 变换格式,见 3.16 节);IP 为网络层协议类型(IPv6 时显示 IP6);
  • f1034b9326b2.36366 > public1.alidns.com.https:源地址.源端口 > 目标地址.目标端口。默认对 IP 做反向解析(本机名 f1034b9326b2、对端 public1.alidns.com)、对端口做服务名解析(.https),加 -nn 后全部显示为数字(见 3.5 节);
  • Flags [S]:TCP 控制位。[S]=SYN(发起连接)、[S.]=SYN+ACK(同意连接)、[.]=ACK(确认)、[P.]=PSH+ACK(推送数据)、[F.]=FIN+ACK(正常关闭)、[R.]=RST+ACK(异常重置)——组合读法见 4.4 节;
  • seq 2770491245 / ack 2770491246:TCP 序列号与确认号(相对序号,ack 1 即「你的第一个字节我收到了」);win 64240 / options [...] / length 0:窗口大小、TCP 选项(MSS、SACK、时间戳、窗口缩放)、应用层载荷字节数。

💡 技术拓展:Linux 下常用抓包/网络观测工具对比——

工具交互形态输出特点与适用场景
tcpdump命令行文本 / pcap 文件服务器标配、内核态 BPF 过滤性能好,本文主角
tshark命令行文本 / pcapWireshark 的 CLI,解码能力最强(应用层字段级),依赖较重
Wireshark图形界面pcap + 交互分析桌面分析 pcap 的最佳伴侣,服务器上用 tcpdump 抓、拉回本地看
ngrep命令行正则匹配报文内容按「内容」抓包(如匹配 HTTP 关键字),轻量但协议解码弱
strace命令行系统调用只看单个进程的收发(不经过网卡),与抓包互补

BPF 过滤原语速查(详见 man pcap-filter):

原语示例含义
hosthost 223.5.5.5源或目的为该地址
src / dstsrc host 223.5.5.5仅源 / 仅目的
netnet 223.5.0.0/16匹配网段
portport 443源或目的端口
协议tcp / udp / icmp匹配传输/网络层协议
组合符and / or / not逻辑组合,可加括号

三、参数逐项实测

3.1 不指定 -i:默认抓第一块网卡(eth0)

不指定 -i 时,tcpdump 自动选择 -D 列表中的第一个可用接口(本机为 eth0),从启动起一直抓到手动停止;用 -c 10 让它抓满 10 包后自动退出,同时另开终端用 curl 造流量:

$ timeout 15 tcpdump -c 10 > /root/demo/tcpdump/cap_default.txt 2>&1 &
$ curl -sk -m 6 https://223.5.5.5 -o /dev/null
$ cat /root/demo/tcpdump/cap_default.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:03:54.210794 IP f1034b9326b2.36366 > public1.alidns.com.https: Flags [S], seq 2770491245, win 64240, options [mss 1460,sackOK,TS val 3014965719 ecr 0,nop,wscale 7], length 0
20:03:54.234062 IP public1.alidns.com.https > f1034b9326b2.36366: Flags [S.], seq 449200181, ack 2770491246, win 64240, options [mss 1460], length 0
20:03:54.234120 IP f1034b9326b2.36366 > public1.alidns.com.https: Flags [.], ack 1, win 64240, length 0
20:03:54.235644 IP f1034b9326b2.36366 > public1.alidns.com.https: Flags [P.], seq 1:518, ack 1, win 64240, length 517
20:03:54.235958 IP public1.alidns.com.https > f1034b9326b2.36366: Flags [.], ack 518, win 64240, length 0
20:03:54.239157 IP f1034b9326b2.48525 > 192.168.146.2.domain: 966+ PTR? 5.5.5.223.in-addr.arpa. (40)
20:03:54.240322 IP 192.168.146.2.domain > f1034b9326b2.48525: 966 1/0/0 PTR public1.alidns.com. (72)
20:03:54.257047 IP public1.alidns.com.https > f1034b9326b2.36366: Flags [P.], seq 1:2741, ack 518, win 64240, length 2740
20:03:54.257068 IP f1034b9326b2.36366 > public1.alidns.com.https: Flags [.], ack 2741, win 65535, length 0
20:03:54.257994 IP f1034b9326b2.36366 > public1.alidns.com.https: Flags [P.], seq 518:582, ack 2741, win 65535, length 64
10 packets captured
36 packets received by filter
0 packets dropped by kernel

逐块解读:

  • 头两行:verbose output suppressed... 提示未加 -v;listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes 声明接口、链路类型与默认快照长度 262144 字节(截断对比见 3.10 节);
  • 第 13 行:TCP 三次握手 [S] → [S.] → [.](curl 向 223.5.5.5:443 发起 HTTPS 连接);第 4 行 [P.] 为 TLS ClientHello(517 字节,HTTPS 内容已加密只见长度);第 67 行是 tcpdump 自身的反向解析查询——对 223.5.5.5 做 PTR 查询(5.5.5.223.in-addr.arpa)得到 public1.alidns.com,默认不带 -n 时解析流量也会被抓到,是排障时常见的「意外流量」来源;第 8~10 行为服务端 TLS 握手响应(2740 字节)与后续确认;
  • 结尾三行摘要:10 packets captured(tcpdump 实际读到的包)、36 packets received by filter(内核 BPF 匹配后交给它的包,含因 -c 10 未展示的)、0 packets dropped by kernel(内核缓冲区溢出丢弃数,非 0 说明抓包压力过大)。

3.2 -c:限定抓包数量,抓满自动退出

-c N 抓满 N 个匹配包后自动退出并打印摘要(见 3.1 结尾三行),避免手动 Ctrl+C。配合过滤表达式与 -c 2 抓一对 ICMP:

$ timeout 6 tcpdump -i eth0 -nn -c 2 'host 223.5.5.5' > /root/demo/tcpdump/f1.txt 2>&1 &
$ ping -c 1 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/f1.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:04:52.484647 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 38, seq 1, length 64
20:04:52.505334 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 38, seq 1, length 64
2 packets captured
2 packets received by filter
0 packets dropped by kernel

💡 要点:-c 统计的是「过滤后」的包数。上面的 2 packets received by filter 与 captured 相等说明没有丢包;若两者差距大(如 3.1 的 10 vs 36),说明匹配流量多于显示量,属正常截停。

3.3 -i any:抓所有接口(含方向标注)

-i any 同时监听全部接口,链路类型变为 LINUX_SLL2(Linux cooked v2),回显中会多出**接口名与方向(In/Out)**两列。eth0 Out / eth0 In 明确标注每个包从哪个接口、哪个方向进出,多网卡服务器排查「包到底从哪张卡走」时非常有用:

$ timeout 6 tcpdump -i any -nn -c 6 icmp > /root/demo/tcpdump/any2.txt 2>&1 &
$ ping -c 3 -i 0.3 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/any2.txt
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
20:10:54.455283 eth0  Out IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 51, seq 1, length 64
20:10:54.475838 eth0  In  IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 51, seq 1, length 64
20:10:54.756314 eth0  Out IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 51, seq 2, length 64
20:10:54.776773 eth0  In  IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 51, seq 2, length 64
20:10:55.057162 eth0  Out IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 51, seq 3, length 64
20:10:55.077597 eth0  In  IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 51, seq 3, length 64
6 packets captured
6 packets received by filter
0 packets dropped by kernel

3.4 -i lo:抓回环接口

本机与本机之间的流量走 lo 接口(即使目的地址写的是本机 IP 172.17.0.2 也走 lo),对 127.0.0.1 的 HTTP 服务抓包:

$ nohup python3 -m http.server 18080 --directory /root/demo/tcpdump/www >/dev/null 2>&1 &
$ timeout 6 tcpdump -i lo -nn -c 4 'tcp port 18080' > /root/demo/tcpdump/lo2.txt 2>&1 &
$ curl -s -m 3 http://127.0.0.1:18080/index.html >/dev/null
$ cat /root/demo/tcpdump/lo2.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:11:00.085587 IP 127.0.0.1.45480 > 127.0.0.1.18080: Flags [S], seq 2722685666, win 65495, options [mss 65495,sackOK,TS val 727827580 ecr 0,nop,wscale 7], length 0
20:11:00.085592 IP 127.0.0.1.18080 > 127.0.0.1.45480: Flags [S.], seq 2908832226, ack 2722685667, win 65483, options [mss 65495,sackOK,TS val 727827580 ecr 727827580,nop,wscale 7], length 0
20:11:00.085597 IP 127.0.0.1.45480 > 127.0.0.1.18080: Flags [.], ack 1, win 512, options [nop,nop,TS val 727827580 ecr 727827580], length 0
20:11:00.085633 IP 127.0.0.1.45480 > 127.0.0.1.18080: Flags [P.], seq 1:90, ack 1, win 512, options [nop,nop,TS val 727827580 ecr 727827580], length 89
4 packets captured
26 packets received by filter
0 packets dropped by kernel

⚠️ 注意两个细节:① 抓本机服务一定要指定 -i lo(或 -i any),在 eth0 上抓不到本机到本机的流量;② 回环上的包「发出又收到」被同一接口看到两次方向,26 packets received by filter 是响应方向也匹配所致(抓包窗口内后续 HTTP 数据/FIN 包),而 -c 4 只展示前 4 个。

3.5 -n 与 -nn:停止名称解析

默认回显会把 IP 解析成主机名、端口解析成服务名(见 3.1 节 .https/.domain)。-n 不转换主机地址;-nn 进一步抑制协议等其余字段的名称转换(man 原文:-n 不转换主机地址,-nn 连协议与端口等也不转换):

$ timeout 6 tcpdump -i eth0 -n -c 2 'port 53' > /root/demo/tcpdump/cap_n.txt 2>&1 &
$ python3 -c "import socket; socket.getaddrinfo('www.baidu.com', 80, socket.AF_INET, socket.SOCK_STREAM)" >/dev/null
$ cat /root/demo/tcpdump/cap_n.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:04:17.972653 IP 172.17.0.2.51481 > 192.168.146.2.53: 60018+ A? www.baidu.com. (31)
20:04:17.977483 IP 192.168.146.2.53 > 172.17.0.2.51481: 60018 3/0/0 CNAME www.a.shifen.com., A 110.242.70.57, A 110.242.69.21 (90)
2 packets captured
2 packets received by filter
0 packets dropped by kernel

-nn 在此基础上的实测回显(本例中 -n 与 -nn 输出格式一致,差异见下方 💡):

$ timeout 6 tcpdump -i eth0 -nn -c 2 'port 53' > /root/demo/tcpdump/cap_nn.txt 2>&1 &
$ python3 -c "import socket; socket.getaddrinfo('www.baidu.com', 80, socket.AF_INET, socket.SOCK_STREAM)" >/dev/null
$ cat /root/demo/tcpdump/cap_nn.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:04:22.994503 IP 172.17.0.2.58644 > 192.168.146.2.53: 42702+ A? www.baidu.com. (31)
20:04:22.997293 IP 192.168.146.2.53 > 172.17.0.2.58644: 42702 3/0/0 CNAME www.a.shifen.com., A 110.242.69.21, A 110.242.70.57 (93)
2 packets captured
2 packets received by filter
0 packets dropped by kernel

💡 要点:解析行为有真实代价——3.1 节的默认抓包中,tcpdump 自己发出的 PTR 查询也被抓了进来;若 DNS 慢,回显还会卡顿。脚本化抓包一律加 -nn。顺带解读 DNS 报文:60018+ 是事务 ID 与「递归标志」,A? 表示 A 记录查询,应答 3/0/0 = 3 条资源记录(1 条 CNAME 别名 www.a.shifen.com + 2 条 A 地址)/0 授权/0 附加。

3.6 -w:原始包写入 pcap 文件

-w 把原始报文(含链路层头)以 libpcap 格式落盘,供 Wireshark 等工具离线分析。造流量(ping + curl)的同时抓取 ICMP 与 TCP:

$ timeout 10 tcpdump -i eth0 -nn -w /root/demo/tcpdump/demo.pcap 'tcp or icmp' >/dev/null 2>&1 &
$ ping -c 2 -i 0.3 223.5.5.5 >/dev/null
$ curl -sk -m 6 https://223.5.5.5 -o /dev/null
$ ls -l /root/demo/tcpdump/demo.pcap
-rw-r--r-- 1 tcpdump tcpdump 4096 Oct 15 20:04 /root/demo/tcpdump/demo.pcap

⚠️ 注意文件属主是 tcpdump 用户而非 root——tcpdump 启动后默认降权(-Z tcpdump),写出文件归该用户。这个特性在 3.18 节的轮转场景会引发真实的权限坑。

3.7 -r:读回 pcap 文件

-r 读取 pcap 并像实时抓包一样解析显示,过滤表达式同样生效:

$ tcpdump -nn -r /root/demo/tcpdump/demo.pcap 2>&1 | head -8
reading from file /root/demo/tcpdump/demo.pcap, link-type EN10MB (Ethernet), snapshot length 262144
20:04:27.717990 IP 192.0.2.1.80 > 172.17.0.2.39868: Flags [R.], seq 271339237, ack 2021831103, win 64240, length 0
20:04:28.003624 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 35, seq 1, length 64
20:04:28.024118 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 35, seq 1, length 64
20:04:28.304508 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 35, seq 2, length 64
20:04:28.324797 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 35, seq 2, length 64
20:04:28.328824 IP 172.17.0.2.50940 > 223.5.5.5.443: Flags [S], seq 1344610284, win 64240, options [mss 1460,sackOK,TS val 3014999837 ecr 0,nop,wscale 7], length 0
20:04:28.349538 IP 223.5.5.5.443 > 172.17.0.2.50940: Flags [S.], seq 1273132536, ack 1344610285, win 64240, options [mss 1460], length 0

读回后一切照旧:管道统计用 tcpdump -nn -r demo.pcap 2>/dev/null | wc -l(实测 10 包,首行提示走标准错误不计入行数);叠加过滤表达式用 tcpdump -nn -r demo.pcap 'icmp'(实测只回显 3 行 ICMP echo request/reply)。

💡 要点:第 1 行的 192.0.2.1.80 > 172.17.0.2.39868: Flags [R.] 是抓包窗口内本机 80 端口收到的一笔复位置连接(服务器上其他业务的正常流量),说明 -w 忠实记录窗口内所有匹配包——真实服务器的抓包几乎总有「背景流量」,读回后靠过滤表达式聚焦。

3.8 -A:ASCII 显示应用层内容(抓 HTTP 明文)

-A 把每个包按 ASCII 渲染,抓 HTTP 等明文协议时可直读请求与响应。对本地 HTTP 服务抓完整会话:

$ timeout 6 tcpdump -i lo -nn -A -s0 'tcp port 18080' > /root/demo/tcpdump/http3.txt 2>&1 &
$ curl -s -m 3 http://127.0.0.1:18080/index.html
$ cat /root/demo/tcpdump/http3.txt

curl 返回页面内容 <h1>tcpdump demo page</h1>(与站点固定装置一致)。抓包文件内容如下(为控制篇幅,非数据包下方 1~2 行头部字节的乱码渲染行从略,仅保留三个数据包的字节行;所有行均逐字取自实测日志):

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:23:46.846536 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [S], seq 4100481317, win 65495, options [mss 65495,sackOK,TS val 728594341 ecr 0,nop,wscale 7], length 0
20:23:46.846543 IP 127.0.0.1.18080 > 127.0.0.1.57346: Flags [S.], seq 2765856940, ack 4100481318, win 65483, options [mss 65495,sackOK,TS val 728594341 ecr 728594341,nop,wscale 7], length 0
20:23:46.846549 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [.], ack 1, win 512, options [nop,nop,TS val 728594341 ecr 728594341], length 0
20:23:46.846584 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [P.], seq 1:90, ack 1, win 512, options [nop,nop,TS val 728594341 ecr 728594341], length 89
E.....@.@..V..........F..ha&...............
+mw.+mw.GET /index.html HTTP/1.1
Host: 127.0.0.1:18080
User-Agent: curl/7.81.0
Accept: */*

20:23:46.846586 IP 127.0.0.1.18080 > 127.0.0.1.57346: Flags [.], ack 90, win 511, options [nop,nop,TS val 728594341 ecr 728594341], length 0
20:23:46.848612 IP 127.0.0.1.18080 > 127.0.0.1.57346: Flags [P.], seq 1:187, ack 90, win 512, options [nop,nop,TS val 728594343 ecr 728594341], length 186
E...ti@.@...........F........ha............
+mw.+mw.HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.10.12
Date: Thu, 15 Oct 2026 20:23:46 GMT
Content-type: text/html
Content-Length: 27
Last-Modified: Thu, 15 Oct 2026 20:03:52 GMT

20:23:46.848640 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [.], ack 187, win 511, options [nop,nop,TS val 728594343 ecr 728594343], length 0
20:23:46.848659 IP 127.0.0.1.18080 > 127.0.0.1.57346: Flags [P.], seq 187:214, ack 90, win 512, options [nop,nop,TS val 728594343 ecr 728594343], length 27
E..Otj@.@..<........F......g.ha......C.....
+mw.+mw.<h1>tcpdump demo page</h1>

20:23:46.848661 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [.], ack 214, win 511, options [nop,nop,TS val 728594343 ecr 728594343], length 0
20:23:46.848685 IP 127.0.0.1.18080 > 127.0.0.1.57346: Flags [F.], seq 214, ack 90, win 512, options [nop,nop,TS val 728594343 ecr 728594343], length 0
20:23:46.848702 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [F.], seq 90, ack 215, win 512, options [nop,nop,TS val 728594343 ecr 728594343], length 0
20:23:46.848712 IP 127.0.0.1.18080 > 127.0.0.1.57346: Flags [.], ack 91, win 512, options [nop,nop,TS val 728594343 ecr 728594343], length 0

12 packets captured
24 packets received by filter
0 packets dropped by kernel

一次 curl 的完整生命周期尽收眼底:[S]/[S.]/[.] 三次握手 → [P.] 携带 GET 请求原文(方法、路径、Host、User-Agent 一目了然)→ 服务端两个 [P.] 分别回 200 OK + 响应头 与 页面正文 → [F.] 两次挥手关闭。

3.9 -X:十六进制 + ASCII 双栏

-X 同时输出十六进制与 ASCII 两栏,适合核对报文字节(协议分析、payload 特征确认)。这里 dump 的是从 IP 头开始的 84 字节(无 -e 不含以太网头):首字节 45 = IPv4 + 头长 20 字节;0800 是 ICMP 类型/代码(echo request);da31 d16a 起 56 字节是 ping 的固定递增载荷(1011 1213...),请求与应答完全一致——可用它校验链路是否被中间设备改包。抓一对 ICMP 包:

$ timeout 6 tcpdump -i eth0 -nn -X -c 2 icmp > /root/demo/tcpdump/cap_x.txt 2>&1 &
$ ping -c 1 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/cap_x.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:04:42.433647 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 36, seq 1, length 64
	0x0000:  4500 0054 7648 4000 4001 3443 ac11 0002  E..TvH@.@.4C....
	0x0010:  df05 0505 0800 9fcd 0024 0001 da31 d16a  .........$...1.j
	0x0020:  0000 0000 e79d 0600 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
20:04:42.454173 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 36, seq 1, length 64
	0x0000:  4500 0054 ee69 0000 7f01 bd21 df05 0505  E..T.i.....!....
	0x0010:  ac11 0002 0000 a7cd 0024 0001 da31 d16a  .........$...1.j
	0x0020:  0000 0000 e79d 0600 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
2 packets captured
2 packets received by filter
0 packets dropped by kernel

3.10 -s:指定抓包快照长度(snaplen)

-s 限制每包抓取的字节数,只留头部时能减小文件、降低 CPU。-s 96 时监听头显示 snapshot length 96 bytes,且 hex dump 到 0x0050 行只有 2 字节(96 = 14 字节以太网头 + 82 字节 IP 包,后面被截断):

$ timeout 6 tcpdump -i eth0 -nn -s 96 -X -c 1 icmp > /root/demo/tcpdump/cap_s.txt 2>&1 &
$ ping -c 1 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/cap_s.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 96 bytes
20:04:47.459065 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 37, seq 1, length 64
	0x0000:  4500 0054 77b8 4000 4001 32d3 ac11 0002  E..Tw.@.@.2.....
	0x0010:  df05 0505 0800 5169 0025 0001 df31 d16a  ......Qi.%...1.j
	0x0020:  0000 0000 3001 0700 0000 0000 1011 1213  ....0...........
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435                                     45
1 packet captured
2 packets received by filter
0 packets dropped by kernel

与 3.9 节(默认 262144 字节,dump 到 0x0050 行共 4 字节 3435 3637)对比:-s 96 截掉了载荷尾部 2 字节。需要完整内容时用 -s 0(快照长度取接口上限,等价于「一包不落全抓」,3.8 节即用 -s0);只看 TCP 头部时可用 -s 96 这类小值省资源。

3.11 host / src / dst:按主机过滤

host 匹配「源或目的」(3.2 节的 f1 抓包即 host 223.5.5.5,一请求一应答两包);src host/dst host 只匹配单向。src host 223.5.5.5 只看对端发来的应答:

$ timeout 6 tcpdump -i eth0 -nn -c 2 'src host 223.5.5.5' > /root/demo/tcpdump/f2b.txt 2>&1 &
$ ping -c 2 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/f2b.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:11:10.119543 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 52, seq 1, length 64
20:11:11.120997 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 52, seq 2, length 64
2 packets captured
2 packets received by filter
0 packets dropped by kernel

dst host 223.5.5.5 只看本机发往对端的请求:

$ timeout 6 tcpdump -i eth0 -nn -c 2 'dst host 223.5.5.5' > /root/demo/tcpdump/f3b.txt 2>&1 &
$ ping -c 2 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/f3b.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:11:16.126445 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 53, seq 1, length 64
20:11:17.128037 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 53, seq 2, length 64
2 packets captured
2 packets received by filter
0 packets dropped by kernel

3.12 net:按网段过滤

net 223.5.0.0/16 匹配该 CIDR 内任意地址(可再配合 src net/dst net 定方向):

$ timeout 6 tcpdump -i eth0 -nn -c 2 'net 223.5.0.0/16' > /root/demo/tcpdump/f4.txt 2>&1 &
$ ping -c 1 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/f4.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:05:07.560817 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 41, seq 1, length 64
20:05:07.581571 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 41, seq 1, length 64
2 packets captured
2 packets received by filter
0 packets dropped by kernel

3.13 and / or / not:组合过滤

and 同时满足——只看回环上 18080 端口的 HTTP 流量:

$ timeout 6 tcpdump -i lo -nn -c 4 'host 127.0.0.1 and port 18080' > /root/demo/tcpdump/f5b.txt 2>&1 &
$ curl -s -m 3 http://127.0.0.1:18080/index.html >/dev/null
$ cat /root/demo/tcpdump/f5b.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:11:22.155640 IP 127.0.0.1.54178 > 127.0.0.1.18080: Flags [S], seq 1670553612, win 65495, options [mss 65495,sackOK,TS val 727849650 ecr 0,nop,wscale 7], length 0
20:11:22.155647 IP 127.0.0.1.18080 > 127.0.0.1.54178: Flags [S.], seq 1147967199, ack 1670553613, win 65483, options [mss 65495,sackOK,TS val 727849650 ecr 727849650,nop,wscale 7], length 0
20:11:22.155653 IP 127.0.0.1.54178 > 127.0.0.1.18080: Flags [.], ack 1, win 512, options [nop,nop,TS val 727849650 ecr 727849650], length 0
20:11:22.155690 IP 127.0.0.1.54178 > 127.0.0.1.18080: Flags [P.], seq 1:90, ack 1, win 512, options [nop,nop,TS val 727849650 ecr 727849650], length 89
4 packets captured
24 packets received by filter
0 packets dropped by kernel

or 任一满足——DNS 与 ICMP 混合流量(第 3 行是 A 记录查询 60308 > 192.168.146.2.53):

$ timeout 8 tcpdump -i eth0 -nn -c 3 'port 53 or icmp' > /root/demo/tcpdump/f6.txt 2>&1 &
$ ping -c 1 223.5.5.5 >/dev/null
$ python3 -c "import socket; socket.getaddrinfo('www.baidu.com', 80, socket.AF_INET, socket.SOCK_STREAM)" >/dev/null
$ cat /root/demo/tcpdump/f6.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:05:17.594792 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 42, seq 1, length 64
20:05:17.615425 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 42, seq 1, length 64
20:05:17.626378 IP 172.17.0.2.60308 > 192.168.146.2.53: 60150+ A? www.baidu.com. (31)
3 packets captured
3 packets received by filter
0 packets dropped by kernel

not 取反——排除 ARP 与 ICMP,专注 TCP 业务流量(第 1 行为本机 80 端口一笔外部连接的 RST,属抓包窗口内的背景流量):

$ timeout 8 tcpdump -i eth0 -nn -c 4 'not arp and not icmp' > /root/demo/tcpdump/f7.txt 2>&1 &
$ curl -sk -m 6 https://223.5.5.5 -o /dev/null
$ cat /root/demo/tcpdump/f7.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:05:23.805112 IP 192.0.2.1.80 > 172.17.0.2.58186: Flags [R.], seq 808929172, ack 4172062551, win 64240, length 0
20:05:24.640007 IP 172.17.0.2.35752 > 223.5.5.5.443: Flags [S], seq 2494811916, win 64240, options [mss 1460,sackOK,TS val 3015056149 ecr 0,nop,wscale 7], length 0
20:05:24.660528 IP 223.5.5.5.443 > 172.17.0.2.35752: Flags [S.], seq 590684679, ack 2494811917, win 64240, options [mss 1460], length 0
20:05:24.660552 IP 172.17.0.2.35752 > 223.5.5.5.443: Flags [.], ack 1, win 64240, length 0
4 packets captured
6 packets received by filter
0 packets dropped by kernel

3.14 tcp / udp / icmp:按协议过滤

tcp——抓到 curl 发往 223.5.5.5:443 的 SYN/SYN-ACK 握手(也证明 443 端口可达);udp——抓到一次完整的 DNS 查询与应答(含 CNAME 与两条 A 记录);icmp 的实测评见 3.2 节(echo request/reply 成对出现)。

$ timeout 8 tcpdump -i eth0 -nn -c 2 'tcp' > /root/demo/tcpdump/p1b.txt 2>&1 &
$ curl -sk -m 6 https://223.5.5.5 -o /dev/null
$ cat /root/demo/tcpdump/p1b.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:11:36.584644 IP 172.17.0.2.43070 > 223.5.5.5.443: Flags [S], seq 1056067448, win 64240, options [mss 1460,sackOK,TS val 3015428093 ecr 0,nop,wscale 7], length 0
20:11:36.605856 IP 223.5.5.5.443 > 172.17.0.2.43070: Flags [S.], seq 339891721, ack 1056067449, win 64240, options [mss 1460], length 0
2 packets captured
17 packets received by filter
0 packets dropped by kernel
$ timeout 6 tcpdump -i eth0 -nn -c 2 'udp' > /root/demo/tcpdump/p2.txt 2>&1 &
$ python3 -c "import socket; socket.getaddrinfo('www.baidu.com', 80, socket.AF_INET, socket.SOCK_STREAM)" >/dev/null
$ cat /root/demo/tcpdump/p2.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:05:38.829566 IP 172.17.0.2.47749 > 192.168.146.2.53: 55930+ A? www.baidu.com. (31)
20:05:38.832351 IP 192.168.146.2.53 > 172.17.0.2.47749: 55930 3/0/0 CNAME www.a.shifen.com., A 110.242.70.57, A 110.242.69.21 (93)
2 packets captured
2 packets received by filter
0 packets dropped by kernel

3.15 -v / -vv / -vvv:详细程度递增

-v 解码并显示 IP 头字段(tos/ttl/id/offset/flags/proto/length)与协议细节(ICMP 的 id/seq、TTL 等),且不再有 verbose output suppressed 提示行;-vv 输出更多协议字段(本例 ICMP 无增量可见);-vvv 为最详级别(主要影响复杂协议如 ISAKMP/ESP 的解码),日常排障 -v 足够:

$ timeout 6 tcpdump -i eth0 -nn -v -c 2 icmp > /root/demo/tcpdump/v1.txt 2>&1 &
$ ping -c 1 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/v1.txt
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:05:43.838821 IP (tos 0x0, ttl 64, id 49874, offset 0, flags [DF], proto ICMP (1), length 84)
    172.17.0.2 > 223.5.5.5: ICMP echo request, id 43, seq 1, length 64
20:05:43.859392 IP (tos 0x0, ttl 127, id 514, offset 0, flags [none], proto ICMP (1), length 84)
    223.5.5.5 > 172.17.0.2: ICMP echo reply, id 43, seq 1, length 64
2 packets captured
2 packets received by filter
0 packets dropped by kernel

-vv 的实测回显(ICMP 场景与 -v 输出粒度一致,无增量字段,仅确认详细级别生效):

$ timeout 6 tcpdump -i eth0 -nn -vv -c 1 icmp > /root/demo/tcpdump/v2.txt 2>&1 &
$ ping -c 1 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/v2.txt
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:05:48.863886 IP (tos 0x0, ttl 64, id 51593, offset 0, flags [DF], proto ICMP (1), length 84)
    172.17.0.2 > 223.5.5.5: ICMP echo request, id 44, seq 1, length 64
1 packet captured
2 packets received by filter
0 packets dropped by kernel

💡 要点:请求 ttl 64(本机默认初值)、应答 ttl 127——回包经 1 跳到达(128−1),且本环境出口为 NAT/代理形态。TTL 是判断「隔了几跳」的硬指标:应答 TTL 与常见初值(64/128/255)相减即为回程跳数。

3.16 -t 与 -tttt:时间戳格式

-t 不显示时间戳(关注内容时更清爽);-tttt 显示「年-月-日 时:分:秒.微秒」完整格式(跨天分析、与日志系统对时必备);另有两个冷门变体:-tt(Unix 纪元秒,便于脚本计算间隔)、-ttt(与上一包的相对时间差,看「每包间隔」最直观)。

$ timeout 6 tcpdump -i eth0 -nn -t -c 2 icmp > /root/demo/tcpdump/t1.txt 2>&1 &
$ ping -c 1 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/t1.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 45, seq 1, length 64
IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 45, seq 1, length 64
2 packets captured
2 packets received by filter
0 packets dropped by kernel

-tttt 的实测回显:

$ timeout 6 tcpdump -i eth0 -nn -tttt -c 2 icmp > /root/demo/tcpdump/t2.txt 2>&1 &
$ ping -c 1 223.5.5.5 >/dev/null
$ cat /root/demo/tcpdump/t2.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
2026-10-15 20:05:58.915005 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 46, seq 1, length 64
2026-10-15 20:05:58.935442 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 46, seq 1, length 64
2 packets captured
2 packets received by filter
0 packets dropped by kernel

3.17 -l:标准输出行缓冲(配合管道实时处理)

tcpdump 默认向管道输出「块缓冲」,管道下游(grep/awk)要攒够一块才见到数据;-l 改为行缓冲,边抓边处理。典型组合:tcpdump -nn -l icmp | tee icmp.log | grep -i request(同时落盘与实时过滤)。实测用管道过滤 ICMP 行:

$ (timeout 6 tcpdump -i eth0 -nn -l -c 2 icmp 2>/dev/null | grep -i echo) &
$ ping -c 1 223.5.5.5 >/dev/null
20:06:03.940261 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 47, seq 1, length 64
20:06:03.960798 IP 223.5.5.5 > 172.17.0.2: ICMP echo reply, id 47, seq 1, length 64

3.18 -G / -W:按时间轮转写文件

-G 秒数 让 -w 每 N 秒换一个新文件;-W 数量 限制滚动文件数(配合 -C 则是按大小轮转)。文件名若含 %d 之外的 strftime 时间格式(如 %H%M%S)可保证文件名唯一。先看一个真实的权限坑:把轮转文件放进 root 属主的目录(/root/demo/tcpdump/rot/,755),首个文件能创建,但轮转重开文件时 tcpdump 已降权为 tcpdump 用户,报 Permission denied 后进程直接退出(g.log 连统计摘要都没打印),轮转后的包全部丢失:

$ rm -f /root/demo/tcpdump/rot/*
$ timeout 8 tcpdump -i eth0 -nn -w /root/demo/tcpdump/rot/t_%H%M%S.pcap -G 2 icmp > /root/demo/tcpdump/rot/g.log 2>&1 &
$ ping -i 0.3 -c 12 223.5.5.5 >/dev/null
$ ls -l /root/demo/tcpdump/rot/
total 8
-rw-r--r-- 1 root    root    151 Oct 15 21:02 g.log
-rw-r--r-- 1 tcpdump tcpdump 822 Oct 15 21:02 t_210238.pcap
$ cat /root/demo/tcpdump/rot/g.log
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
tcpdump: /root/demo/tcpdump/rot/t_210240.pcap: Permission denied

修正:把输出目录放开给 tcpdump 用户可写(如 /tmp/gg 设 777,或预先 chown tcpdump),轮转立即正常——2 秒一个轮转点,实测 23 个包分布在 3 个文件中:

$ rm -f /tmp/gg/*; chmod 777 /tmp/gg
$ timeout 8 tcpdump -i eth0 -nn -w /tmp/gg/t_%H%M%S.pcap -G 2 icmp > /tmp/gg/g.log 2>&1 &
$ ping -i 0.3 -c 12 223.5.5.5 >/dev/null
$ ls -l /tmp/gg/
total 16
-rw-r--r-- 1 root    root     164 Oct 15 21:02 g.log
-rw-r--r-- 1 tcpdump tcpdump  822 Oct 15 21:02 t_210247.pcap
-rw-r--r-- 1 tcpdump tcpdump 1620 Oct 15 21:02 t_210249.pcap
-rw-r--r-- 1 tcpdump tcpdump  252 Oct 15 21:02 t_210251.pcap
$ cat /tmp/gg/g.log
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
23 packets captured
23 packets received by filter
0 packets dropped by kernel

💡 要点与拓展:① 文件名中的 % 系列按 strftime(3) 展开——若写成 rot_%03d.pcap,%d 会被展开为「日期中的日」(本例 15 日),所有轮转都写进同一个 rot_015.pcap 相互覆盖,实测最终只剩 1 个 138 字节的文件;② -W 与 -C 文件大小 组合按「大小」滚动是长抓任务更常用的姿势;③ 长时间轮转务必给磁盘留空间并配置 -z 脚本压缩旧文件。

3.19 -e:显示二层链路层头(MAC 地址)

-e 在每行前追加链路层信息(以太网则为 MAC 地址与 ethertype):

$ timeout 6 tcpdump -i eth0 -nn -e -c 2 icmp > /root/demo/tcpdump/e1.txt 2>&1 &
$ ping -c 1 172.17.0.1 >/dev/null
$ cat /root/demo/tcpdump/e1.txt
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:06:20.300006 fe:7b:dc:56:f2:9d > e6:df:fb:96:2e:f4, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 172.17.0.1: ICMP echo request, id 49, seq 1, length 64
20:06:20.300038 e6:df:fb:96:2e:f4 > fe:7b:dc:56:f2:9d, ethertype IPv4 (0x0800), length 98: 172.17.0.1 > 172.17.0.2: ICMP echo reply, id 49, seq 1, length 64
2 packets captured
2 packets received by filter
0 packets dropped by kernel

fe:7b:dc:56:f2:9d 为本机 eth0 的 MAC,e6:df:fb:96:2e:f4 为网关的 MAC;length 98 也变为含 14 字节以太网头的帧长(84+14)。排查二层问题(MAC 冲突、漂移、VLAN 标签 vlan 原语)必加 -e。

四、实战示例

4.1 HTTP 明文排障全流程(本地服务)

组合 -i lo + host/port 过滤 + -A -s0,直接看到浏览器/curl 发了什么、服务端回了什么(完整实测回显见 3.8 节:GET /index.html HTTP/1.1 → HTTP/1.0 200 OK → <h1>tcpdump demo page</h1>)。把过滤对象换成业务端口(如 -i eth0 -A -s0 'host 10.0.0.5 and port 8080')即可用于真实服务,注意 HTTPS 流量在 -A 下只能看到 TLS 密文长度。

$ timeout 6 tcpdump -i lo -nn -A -s0 'tcp port 18080' > /root/demo/tcpdump/http3.txt 2>&1 &
$ curl -s -m 3 http://127.0.0.1:18080/index.html
$ cat /root/demo/tcpdump/http3.txt
(输出节选(实测关键行,完整回显见 3.8 节))
20:23:46.846536 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [S], seq 4100481317, win 65495, options [mss 65495,sackOK,TS val 728594341 ecr 0,nop,wscale 7], length 0
+mw.+mw.GET /index.html HTTP/1.1
Host: 127.0.0.1:18080
User-Agent: curl/7.81.0
Accept: */*
+mw.+mw.HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.10.12
Content-Length: 27
+mw.+mw.<h1>tcpdump demo page</h1>

验证结果:curl 拿到 <h1>tcpdump demo page</h1>(rc=0),抓包里请求行、响应状态行与响应体三段明文全部可读,证明本步排障链路成立。

4.2 抓一次 DNS 解析全程

命令与完整回显见 3.5 节 -n 实测(port 53 过滤 + getaddrinfo 造流量,查询 5ms 内应答)。解读:60018+ 是事务 ID 与递归标志,A? 表示 A 记录查询;应答 3/0/0 = 3 条资源记录(1 条 CNAME 别名 www.a.shifen.com + 2 条 A 地址)、0 授权、0 附加。排障要点:只见查询不见应答,检查 resolv.conf 指向的 DNS 是否可达(结合 ping);应答码为 3(NXDomain)说明域名不存在。

$ timeout 6 tcpdump -i eth0 -n -c 2 'port 53' > /root/demo/tcpdump/cap_n.txt 2>&1 &
$ python3 -c "import socket; socket.getaddrinfo('www.baidu.com', 80, socket.AF_INET, socket.SOCK_STREAM)" >/dev/null
$ cat /root/demo/tcpdump/cap_n.txt
(输出节选(实测首尾),完整回显见 3.5 节)
20:04:17.972653 IP 172.17.0.2.51481 > 192.168.146.2.53: 60018+ A? www.baidu.com. (31)
20:04:17.977483 IP 192.168.146.2.53 > 172.17.0.2.51481: 60018 3/0/0 CNAME www.a.shifen.com., A 110.242.70.57, A 110.242.69.21 (90)
2 packets captured
2 packets received by filter
0 packets dropped by kernel

验证结果:2 packets captured 与查询/应答各 1 包对上,查询到应答间隔约 5ms,本机 DNS 解析链路正常。

4.3 抓包存证,交给 Wireshark 深挖

服务器上只负责「抓到」,复杂解码交给桌面端(完整实测见 3.6/3.7 节):-w demo.pcap 落盘 → scp 拉回本地 → Wireshark 打开;服务器上可先用 -r + 过滤快速预览(tcpdump -nn -r demo.pcap 'icmp')确认抓没抓对,再用 | wc -l 统计包量。

$ timeout 10 tcpdump -i eth0 -nn -w /root/demo/tcpdump/demo.pcap 'tcp or icmp' >/dev/null 2>&1 &
$ ping -c 2 -i 0.3 223.5.5.5 >/dev/null
$ curl -sk -m 6 https://223.5.5.5 -o /dev/null
$ ls -l /root/demo/tcpdump/demo.pcap
$ tcpdump -nn -r /root/demo/tcpdump/demo.pcap 2>&1 | head -8
(输出节选(实测首尾),完整回显见 3.6/3.7 节)
-rw-r--r-- 1 tcpdump tcpdump 4096 Oct 15 20:04 /root/demo/tcpdump/demo.pcap
reading from file /root/demo/tcpdump/demo.pcap, link-type EN10MB (Ethernet), snapshot length 262144
20:04:27.717990 IP 192.0.2.1.80 > 172.17.0.2.39868: Flags [R.], seq 271339237, ack 2021831103, win 64240, length 0
20:04:28.003624 IP 172.17.0.2 > 223.5.5.5: ICMP echo request, id 35, seq 1, length 64

验证结果:pcap 文件非零落盘(4096 字节)、-r 读回能解析出链路层与报文行,说明存证文件有效,可放心交给 Wireshark。

4.4 读懂 TCP 握手与挥手(Flags 组合)

一次正常 HTTP 会话的 Flags 序列(实测见 3.8 节):[S](客户端 SYN)→ [S.](服务端 SYN+ACK,说明端口开放且可达)→ [.](三次握手完成)→ [P.](携带 GET 数据)→ [P.](服务端 200 OK)→ [F.]×2(双方正常关闭)。异常特征:只看到客户端反复 [S] 而无 [S.]——对端不可达或防火墙静默丢包;出现 [R.]——对端拒绝(端口未监听/被重置),实例见 3.7 与 3.13 节回显中的 Flags [R.]。

(输出节选(实测关键行):正常握手序列取自 3.8 节,[R.] 拒绝形态取自 3.7 节)
20:23:46.846536 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [S], seq 4100481317, win 65495, options [mss 65495,sackOK,TS val 728594341 ecr 0,nop,wscale 7], length 0
20:23:46.846543 IP 127.0.0.1.18080 > 127.0.0.1.57346: Flags [S.], seq 2765856940, ack 4100481318, win 65483, options [mss 65495,sackOK,TS val 728594341 ecr 728594341,nop,wscale 7], length 0
20:23:46.846549 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [.], ack 1, win 512, options [nop,nop,TS val 728594341 ecr 728594341], length 0
20:23:46.846584 IP 127.0.0.1.57346 > 127.0.0.1.18080: Flags [P.], seq 1:90, ack 1, win 512, options [nop,nop,TS val 728594341 ecr 728594341], length 89
20:04:27.717990 IP 192.0.2.1.80 > 172.17.0.2.39868: Flags [R.], seq 271339237, ack 2021831103, win 64240, length 0

验证要点:前三行 Flags [S] → [S.] → [.] 依次成对出现即三次握手完成;最后一行 [R.] 是读到 [R.] 形态时判定「对端拒绝」的直接证据。

4.5 定位「端口不通」的层次

先用 tcp 过滤确认 TCP 层(实测见 3.14 节:[S] 与 [S.] 成对 = 443 可达);再按 3.13 节组合 host + port 收窄到具体对端与端口;若只有 [S] 没有 [S.],配合 not arp and not icmp 排除二层与 ICMP 干扰后,即可判定为对端服务未监听或中间防火墙丢弃——再上 traceroute(同系列文档)定位是「哪一跳」开始丢。

$ timeout 8 tcpdump -i eth0 -nn -c 2 'tcp' > /root/demo/tcpdump/p1b.txt 2>&1 &
$ curl -sk -m 6 https://223.5.5.5 -o /dev/null
$ cat /root/demo/tcpdump/p1b.txt
(输出节选(实测首尾),完整回显见 3.14 节)
20:11:36.584644 IP 172.17.0.2.43070 > 223.5.5.5.443: Flags [S], seq 1056067448, win 64240, options [mss 1460,sackOK,TS val 3015428093 ecr 0,nop,wscale 7], length 0
20:11:36.605856 IP 223.5.5.5.443 > 172.17.0.2.43070: Flags [S.], seq 339891721, ack 1056067449, win 64240, options [mss 1460], length 0
2 packets captured
17 packets received by filter
0 packets dropped by kernel

验证结果:[S] 与 [S.] 在 21ms 内成对出现,判定 223.5.5.5:443 可达——这正是本节「端口通」判定的实测依据。

五、注意事项与常见问题

Q1:运行报 Operation not permitted? 抓包需要 CAP_NET_RAW 能力。root 用户天然具备;普通用户需 sudo 执行,或由管理员授予能力(setcap cap_net_raw+ep /usr/bin/tcpdump)。受限环境(无特权)下 tcpdump 无法抓包,可改用只读系统观测工具替代。

Q2:抓不到包,按什么顺序排查? ① 接口选对没有——tcpdump -D 确认,本机流量在 lo、跨机流量在业务口,拿不准就 -i any(见 3.3/3.4 节);② 过滤表达式方向写反没有——src/dst 是相对本机的(见 3.11 节);③ 流量真的存在吗——先 ping/curl 造一波;④ 过滤语法是否被 shell 吞了——表达式务必加引号(见 Q4);⑤ 内核是否匹配了但没显示——看 received by filter 与 captured 的差值(见 3.2 节)。

Q3:-n 与 -nn 到底差在哪? man 原文:-n 不转换主机地址;-nn 连协议与端口等也不转换。本版本(4.99.1)实测中 -n 的回显端口已显示为数字(3.5 节 .53),默认则是 .domain/.https 服务名(3.1 节)——老文档「-n 只管地址、-nn 才管端口」的说法与本版行为有出入。脚本统一用 -nn 即可,还能避免 tcpdump 自身的 DNS 查询流量混入抓包结果。

Q4:过滤表达式为什么必须加引号? BPF 表达式里的括号、and、主机名等会被 shell 优先解释;如 'not (host 1.2.3.4 or host 5.6.7.8)' 不加引号会被 shell 当作子命令执行而报语法错。习惯写法:单引号包住整个表达式,内部用双引号场景除外。表达式错误会在启动时立即报 syntax error,不会静默。

Q5:-w 写出的文件属主为什么是 tcpdump?以及轮转报 Permission denied? tcpdump 启动后默认降权为 tcpdump 用户(-Z),文件属主随之改变(3.6 节实测)。由此推导:-G 轮转「重新打开文件」也以该用户身份进行——root 属主目录下轮转会报 Permission denied 并丢失后续包(3.18 节实测),务必保证输出目录对 tcpdump 用户可写(chmod/chown 或放 /tmp)。

Q6:长时间挂抓包要注意什么? ① 磁盘:-w 文件会持续膨胀,长任务用 -C 100(每 100MB 切文件)配 -W 20(滚动覆盖)并监控空间;② 性能:加精确过滤表达式减少进入用户态的包量,关注 dropped by kernel 是否非 0;③ 合规:抓包内容可能含用户敏感数据,落盘文件要有访问控制并及时清理;④ HTTPS 只能看到加密载荷(3.1 节实测可见长度但不可读内容);⑤ 退出方式:前台 Ctrl+C、后台 kill <pid>(勿用 kill -9,普通 TERM 即可让 tcpdump 刷出统计摘要并正常关闭 -w 文件,摘要三行含义见 3.1 节)。

六、参考链接