跳到主要内容

Tcpdump 抓包与网络排查指南

在日常的系统运维、容器排查和微服务调试中,网络问题(如连接超时、丢包、重传、协议错误)是最棘手的问题之一。tcpdump 是一款强大且经典的命令行网络抓包工具,它能够截获流经网卡的网络数据包,并支持极其丰富的过滤规则。

本文整理了 tcpdump 的核心参数、高频实战过滤表达式、容器环境下的抓包技巧,以及如何配合 Wireshark 进行深度分析。


1. 核心常用参数速查

在执行 tcpdump 命令时,合理搭配参数可以帮助我们快速、清晰地观察数据流,或者将数据保存到文件中。

参数说明建议与备注
-i <interface>指定监听的网卡接口(如 eth0, anyany 表示监听所有网卡,但在某些系统上可能不支持混杂模式
-n不把 IP 地址解析为主机名必带参数,避免 DNS 解析带来延迟和干扰
-nn不把端口号解析为服务名(如 80 不解析为 http必带参数,直接显示数字端口
-c <count>抓取指定数量的数据包后自动退出生产环境抓包时建议带上,防止刷屏或撑爆磁盘
-s <snaplen>设置抓取每个数据包的字节数-s 0 表示抓取完整的数据包(默认),排查应用层协议(如 HTTP/gRPC)时必须完整抓取
-v, -vv, -vvv输出更详细的报文协议信息级别越高,输出的信息越详细(如 TTL、TOS、TCP 选项等)
-X以 Hex(十六进制)和 ASCII 格式打印数据包内容适合排查明文协议(如 HTTP, Redis, Memcached)的内容
-A仅以 ASCII 码格式打印数据包内容适合快速查看 HTTP 请求体或响应体中的文本
-w <file.pcap>将抓取到的原始数据包写入 .pcap 文件生产标准做法,保存后可下载到本地用 Wireshark 深度分析
-r <file.pcap>从保存的 .pcap 文件中读取并分析数据包离线分析时使用

2. 高频实战过滤表达式

tcpdump 强大的核心在于其过滤表达式(Filter Expression)。通过合理组合限定词,我们可以从海量流量中精确筛选出目标报文。

基础过滤(按 IP、端口、协议)

# 1. 监听指定网卡上所有经过特定 IP 的流量(源或目的)
tcpdump -i eth0 -nn host 192.168.1.100

# 2. 监听特定源 IP 或目的 IP 的流量
tcpdump -i eth0 -nn src 192.168.1.100
tcpdump -i eth0 -nn dst 192.168.1.200

# 3. 监听特定端口的流量(TCP 或 UDP)
tcpdump -i eth0 -nn port 80
tcpdump -i eth0 -nn src port 8080

# 4. 监听特定网段的流量
tcpdump -i eth0 -nn net 10.244.0.0/16

# 5. 监听特定协议(tcp, udp, icmp, arp 等)
tcpdump -i eth0 -nn icmp

逻辑组合过滤(and, or, not)

通过逻辑运算符,可以构建非常复杂的过滤场景:

# 1. 抓取来自 192.168.1.100 且目的端口是 80 或 443 的 TCP 报文
tcpdump -i eth0 -nn 'tcp and src host 192.168.1.100 and (dst port 80 or dst port 443)'

# 2. 抓取网卡上除了 SSH (22) 之外的所有流量,防止抓包数据刷屏
tcpdump -i eth0 -nn 'not port 22'

# 3. 抓取主机 A 与主机 B 之间通信的所有非 ICMP 报文
tcpdump -i eth0 -nn 'host 192.168.1.10 and host 192.168.1.20 and not icmp'

3. 生产运维高频实战场景

场景一:排查 HTTP 明文请求与响应体

当怀疑微服务之间的 HTTP 调用参数有问题时,可以直接在终端打印 ASCII 内容:

# 抓取 8080 端口的 HTTP 流量,并以 ASCII 打印,限制抓取 100 个包
tcpdump -i eth0 -nn -A -s 0 port 8080 -c 100

场景二:排查 TCP 三次握手与连接重置(RST)

当客户端报 Connection reset by peerConnection refused 时,我们需要观察 TCP 标志位(Flags):

# 抓取所有带有 RST 标志位的 TCP 报文(常用于排查连接被异常中断)
tcpdump -i any -nn 'tcp[tcpflags] & tcp-rst != 0'

# 抓取所有带有 SYN 或 FIN 标志位的报文(排查连接建立与释放)
tcpdump -i any -nn 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0'

场景三:排查 DNS 解析异常

当系统报错 Temporary failure in name resolution,怀疑 DNS 慢或解析失败:

# 监听 53 端口(DNS 默认端口)的 UDP 报文,查看解析请求与回复
tcpdump -i any -nn udp port 53

4. 容器与 Kubernetes 环境下的抓包技巧

在 Kubernetes (K8s) 或 Docker 容器环境中,由于容器内通常没有安装 tcpdump,且容器网络通过 Network Namespace 进行了隔离,直接在宿主机上执行 tcpdump -i eth0 往往抓不到容器内部的局部流量。

方法一:定位容器网卡,在宿主机抓包(Docker)

  1. 获取容器的 PID

    docker inspect --format '{{.State.Pid}}' <container_id_or_name>
    # 假设输出为 12345
  2. 利用 nsenter 进入容器的网络命名空间(推荐,最硬核且绿色的方式,无需在容器内安装任何工具):

    # 进入 PID 为 12345 的容器网络命名空间,并在其中执行宿主机的 tcpdump
    nsenter -t 12345 -n tcpdump -i any -nn -w /tmp/container_traffic.pcap
    提示

    关于 nsenter 的详细高级用法,请参考知识库中的 Nsenter 命名空间穿梭指南 文档。

方法二:使用 K8s 临时容器(Ephemeral Containers)抓包

在 Kubernetes 1.23+ 中,可以使用 kubectl debug 启动一个带有 tcpdump 的临时工具容器,并共享目标 Pod 的网络命名空间:

# 往目标 Pod 中注入一个包含 tcpdump 的 netshoot 镜像容器,并直接开始抓包
kubectl debug -it <pod_name> -n <namespace> --image=nicolaka/netshoot -- tcpdump -i any -nn -c 50

5. 配合 Wireshark 进行深度分析

虽然 tcpdump 可以在终端输出报文,但对于复杂的 TCP 粘包、乱序重传、SSL/TLS 握手排查,图形化工具 Wireshark 才是终极利器。

生产标准抓包与分析工作流

  1. 在服务器上抓包并保存为 pcap 文件(限制大小或数量,防止撑爆磁盘):

    # 抓取 eth0 上 10000 个包,保存到 /tmp/target.pcap
    tcpdump -i eth0 -nn -s 0 -c 10000 -w /tmp/target.pcap
  2. 将 pcap 文件下载到本地

    # 在本地终端执行 scp 下载
    scp user@server_ip:/tmp/target.pcap ./
  3. 使用 Wireshark 打开分析

    • Follow TCP Stream:在任意 TCP 包上右键,选择 Follow -> TCP Stream,可以完整还原应用层的明文会话(如 Redis 命令、HTTP 报文)。
    • 查看重传与丢包:在上方过滤器输入 tcp.analysis.flags,Wireshark 会自动高亮标出所有的重传包(Retransmission)、乱序包(Out-of-Order)和 ACK 丢失,帮您快速定位网络链路质量问题。