tcpdump指南:从基础抓包到 BPF 高级过滤与生产实战

📌 本文亮点:覆盖 tcpdump 全部核心知识点——常用选项速查、BPF 过滤语法从入门到字节偏移高级用法、TCP 标志位精准抓包、生产环境抓包策略与性能优化,附速查表一键收藏!

前言

网络排障时,你是否遇到过这些问题:服务明明收到了请求却返回 RST?DNS 解析偶尔超时却不知道查询是否发出?线上疑似 SYN 洪水却无从确认?tcpdump 是解决这些问题的第一利器,但很多人只会 tcpdump -i eth0,面对高流量环境手足无措,过滤表达式写不对、抓包丢包、pcap 文件撑爆磁盘。

本文从零基础出发,系统梳理 tcpdump 的完整知识体系,重点攻克 BPF 过滤语法这一核心技能,最终给出生产环境可直接复用的命令模板。


一、基础概念与安装

1.1 tcpdump 是什么

tcpdump 是基于 libpcap 的命令行网络数据包抓取工具,能够捕获流经网络接口的原始数据包,打印到终端或写入 .pcap 文件,是网络诊断、安全分析和协议调试的必备工具。

💡 核心优势:BPF 过滤器在内核层面生效,只有匹配的数据包才会到达用户空间,高流量环境下过滤极为高效。

1.2 安装方式

# Debian/Ubuntu
sudo apt install tcpdump

# RHEL/CentOS
sudo yum install tcpdump

# macOS(通常已预装)
brew install tcpdump

# Alpine
apk add tcpdump

二、基本语法与常用选项

2.1 语法结构

tcpdump [选项] [BPF 过滤表达式]

2.2 接口选择

接口相关选项:

选项说明示例
-i <接口>指定监听接口tcpdump -i eth0
-i any监听所有接口tcpdump -i any
-D列出可用接口tcpdump -D

⚠️ -i any 是 Linux 的伪接口,不支持混杂模式。如需看到所有流量(不仅是单播到本机的),请指定具体物理接口。

2.3 抓包控制

抓包行为控制选项:

选项说明示例
-c <数量>抓取 N 个包后停止tcpdump -c 100
-s <字节数>每包抓取长度(snaplen)tcpdump -s 0(全量)
-w <文件>写入 pcap 文件tcpdump -w capture.pcap
-r <文件>读取 pcap 文件tcpdump -r capture.pcap
-C <MB>文件大小限制,自动轮转tcpdump -C 100 -w capture.pcap
-W <数量>轮转文件最大数量tcpdump -C 100 -W 10 -w capture.pcap
-G <秒>按时间轮转文件tcpdump -G 3600 -w cap_%Y%m%d.pcap

2.4 输出格式

输出显示控制选项:

选项说明示例
-n不解析主机名tcpdump -n
-nn不解析主机名和端口名tcpdump -nn
-v / -vv / -vvv递增详细度tcpdump -vvv
-q简洁输出tcpdump -q
-t不打印时间戳tcpdump -t
-tttt可读日期格式tcpdump -tttt
-e显示以太网头(MAC)tcpdump -e
-X十六进制 + ASCIItcpdump -X
-XX包含以太网头的十六进制tcpdump -XX
-AASCII 输出(适合 HTTP)tcpdump -A
-S绝对 TCP 序列号tcpdump -S
-l行缓冲(可管道)tcpdump -l
-U包缓冲(实时刷新)tcpdump -U

💡 黄金法则:生产环境永远加 -nn,禁止 DNS 反解,避免卡顿和额外流量。


三、BPF 过滤语法(核心技能)

3.1 过滤原语一览

BPF(Berkeley Packet Filter)是 tcpdump 过滤的引擎,由原语组合而成:

原语说明示例
host按主机 IPhost 192.168.1.1
src host源主机src host 10.0.0.5
dst host目的主机dst host 10.0.0.5
net按网段net 192.168.0.0/24
port按端口port 80
src port源端口src port 443
dst port目的端口dst port 53
portrange端口范围portrange 8000-8100
ether host按 MAC 地址ether host aa:bb:cc:dd:ee:ff

3.2 协议快捷过滤

tcpdump tcp            # 所有 TCP 流量
tcpdump udp            # 所有 UDP 流量
tcpdump icmp           # 所有 ICMP(ping)
tcpdump arp            # 所有 ARP
tcpdump ip6            # 所有 IPv6

3.3 逻辑组合(and / or / not)

# AND —— 两个条件同时匹配
tcpdump 'host 192.168.1.1 and port 80'
tcpdump 'tcp and src port 443 and dst host 10.0.0.1'

# OR —— 任一条件匹配
tcpdump 'port 80 or port 443'
tcpdump 'host 192.168.1.1 or host 192.168.1.2'

# NOT —— 排除
tcpdump 'not port 22'
tcpdump 'not arp and not icmp'

# 复合表达式(用引号包裹)
tcpdump 'tcp port 5432 and not host 10.0.0.99'
tcpdump 'port 53 and (udp or tcp)'

⚠️ 含空格或特殊字符的过滤表达式必须用单引号包裹,防止 shell 解析 &|() 等符号。


四、TCP 标志位过滤

TCP 标志位于 TCP 头部第 14 字节(偏移 13),是诊断连接问题的利器。

4.1 使用命名标志(推荐)

# SYN 包(连接建立请求)
tcpdump 'tcp[tcpflags] & tcp-syn != 0'

# ACK 包
tcpdump 'tcp[tcpflags] & tcp-ack != 0'

# RST 包(连接重置/拒绝)
tcpdump 'tcp[tcpflags] & tcp-rst != 0'

# FIN 包(连接关闭)
tcpdump 'tcp[tcpflags] & tcp-fin != 0'

# PSH 包(推送数据)
tcpdump 'tcp[tcpflags] & tcp-push != 0'

# 纯 SYN(SYN=1, ACK=0)—— 新连接请求
tcpdump 'tcp[tcpflags] & tcp-syn != 0 and not tcp[tcpflags] & tcp-ack != 0'

# SYN-ACK(服务端响应)
tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0'

# 连接状态变化包(SYN + FIN + RST)
tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0'

4.2 使用位掩码(底层方式)

TCP 标志位掩码对照:

标志位值说明
FIN0x01连接关闭
SYN0x02连接建立
RST0x04连接重置
PSH0x08推送数据
ACK0x10确认
URG0x20紧急
tcpdump 'tcp[13] & 2 != 0'     # SYN
tcpdump 'tcp[13] & 16 != 0'    # ACK
tcpdump 'tcp[13] & 18 != 0'    # SYN-ACK
tcpdump 'tcp[13] & 1 != 0'     # FIN
tcpdump 'tcp[13] & 4 != 0'     # RST
tcpdump 'tcp[13] & 8 != 0'     # PSH

五、BPF 字节偏移高级过滤

5.1 通用语法

proto[offset:size] operator value
  • protoipip6tcpudpicmparpether
  • offset:协议头部内的字节偏移
  • size1(字节)、2(短整型)、4(整型)
  • operator=!=<<=>>=&

5.2 IP 头部过滤

# TTL 小于 10(经过很多跳)
tcpdump 'ip[8] < 10'

# IP 协议号过滤
tcpdump 'ip[9] = 6'       # TCP(协议号 6)
tcpdump 'ip[9] = 17'      # UDP(协议号 17)
tcpdump 'ip[9] = 1'       # ICMP(协议号 1)
tcpdump 'ip[9] = 50'      # ESP/IPsec(协议号 50)

# IP 包总长度
tcpdump 'ip[2:2] > 1400'  # 大于 1400 字节
tcpdump 'ip[2:2] < 64'    # 小于 64 字节

# 带 IP 选项的包(IHL > 5)
tcpdump 'ip[0] & 0x0f > 5'

# DSCP EF(Expedited Forwarding)
tcpdump 'ip[1] >> 2 = 46'

5.3 ICMP 类型过滤

tcpdump 'icmp[0] == 8'    # Echo Request(ping 请求)
tcpdump 'icmp[0] == 0'    # Echo Reply(ping 响应)
tcpdump 'icmp[0] == 3'    # Destination Unreachable(目标不可达)
tcpdump 'icmp[0] == 11'   # Time Exceeded(路由超时/Traceroute)

5.4 包大小过滤

tcpdump 'greater 1400'    # 包长度 >= 1400
tcpdump 'less 64'         # 包长度 <= 64
tcpdump 'len > 1000'      # 包长度 > 1000

5.5 HTTP 载荷匹配

# 抓取 HTTP GET 请求("GET " = 0x47455420)
tcpdump -A 'tcp dst port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'

# 抓取 HTTP POST 请求("POST" = 0x504f5354)
tcpdump -A 'tcp dst port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354'

# 抓取 HTTP 响应("HTTP" = 0x48545420)
tcpdump -A 'tcp src port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x48545420'

六、VLAN 与隧道过滤

6.1 VLAN 过滤

# 任意 VLAN 标签帧
tcpdump 'vlan'

# 指定 VLAN ID
tcpdump 'vlan 10'

# QinQ(VLAN 200 嵌套在 VLAN 100 内)
tcpdump 'vlan 100 and vlan 200'

# VLAN 内的 IPv4 流量
tcpdump 'vlan and ip'

⚠️ BPF 中 vlan 关键字会改变解码偏移,表达式中 vlan 应放在前面。

6.2 隧道封装过滤

# VXLAN
tcpdump 'vxlan 0x7'              # VNI 7

# Geneve
tcpdump 'geneve 0xb'             # VNI 0xb

# MPLS
tcpdump 'mpls 100000'            # MPLS 标签 100000
tcpdump 'mpls 100000 and mpls 1024'  # 两层 MPLS 标签栈

# PPPoE
tcpdump 'pppoes'                 # 任意 PPPoE 会话
tcpdump 'pppoes 0x27 and ip'    # PPPoE 会话 0x27 + IPv4

七、实战场景示例

7.1 Web 流量分析

# 抓取所有 HTTP/HTTPS 流量
tcpdump -nn -i eth0 'tcp port 80 or tcp port 443'

# 实时查看 HTTP 请求内容(ASCII)
tcpdump -nn -A -i eth0 'tcp port 80'

# 只抓 HTTP 数据包(排除纯 SYN/FIN/ACK)
tcpdump -nn -i eth0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

# 保存到文件供 Wireshark 分析
tcpdump -nn -s 0 -w http.pcap -i eth0 'tcp port 80 or tcp port 443'

7.2 DNS 排障

# 所有 DNS 查询和响应
tcpdump -nn -i any 'udp port 53'

# 指定主机的 DNS 查询
tcpdump -nn -i eth0 'udp port 53 and src host 192.168.1.50'

# TCP DNS(区域传送、大响应)
tcpdump -nn -i eth0 'tcp port 53'

# DNS 到指定服务器
tcpdump -nn -i eth0 'udp port 53 and host 8.8.8.8'

7.3 TCP 连接诊断

# 新连接请求(纯 SYN)
tcpdump -nn 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'

# 连接重置(RST)
tcpdump -nn 'tcp[tcpflags] & tcp-rst != 0'

# 服务端拒绝的连接(RST 来自服务端口)
tcpdump -nn 'tcp[tcpflags] & tcp-rst != 0 and src port 443'

# 连接关闭(FIN)
tcpdump -nn 'tcp[tcpflags] & tcp-fin != 0'

# 完整连接生命周期
tcpdump -nn 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0'

7.4 DHCP 分析

# DHCP 流量
tcpdump -nn -i eth0 'udp port 67 or udp port 68'

# DHCP 详细输出
tcpdump -nn -v -i eth0 'udp port 67 or udp port 68'

7.5 ARP 排障

# 所有 ARP 流量
tcpdump -nn -e -i eth0 'arp'

# ARP 请求(who-has)
tcpdump -nn -e -i eth0 'arp[6:2] = 0x0001'

# ARP 响应
tcpdump -nn -e -i eth0 'arp[6:2] = 0x0002'

7.6 安全与事件响应

# 排除自身 SSH 会话,减少噪声
tcpdump -nn -i eth0 'not port 22'

# SYN 洪水检测
tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'

# 异常 ICMP(大包可能为 ICMP 隧道)
tcpdump -nn -i eth0 'icmp and greater 100'

# ARP 欺骗检测
tcpdump -nn -e -i eth0 'arp'

八、文件保存与读取

8.1 保存到 pcap 文件

# 基本保存
tcpdump -nn -i eth0 -w capture.pcap 'port 80'

# 按文件大小轮转(每个 100MB)
tcpdump -nn -i eth0 -C 100 -w capture.pcap 'port 443'

# 按时间轮转(每小时一个文件)
tcpdump -nn -i eth0 -G 3600 -w 'capture_%H:%M:%S.pcap'

# 环形缓冲:保留最近 10 个 100MB 文件
tcpdump -nn -i eth0 -C 100 -W 10 -w capture.pcap

# 轮转后自动压缩
tcpdump -nn -i eth0 -C 100 -w capture.pcap -z gzip

8.2 读取 pcap 文件

# 基本读取
tcpdump -nn -r capture.pcap

# 读取时应用过滤
tcpdump -nn -r capture.pcap 'host 192.168.1.10 and port 443'

# 读取并查看 HTTP 内容
tcpdump -nn -A -r capture.pcap 'tcp port 80'

# 转为文本供 grep 搜索
tcpdump -nn -A -r capture.pcap > capture.txt

# 统计源 IP 分布
tcpdump -nn -r capture.pcap | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn

8.3 双路输出(终端 + 文件)

# 同时写文件和输出到终端
tcpdump -nn -U -l -i eth0 -w - | tee capture.pcap | tcpdump -r -

九、时间戳格式控制

# 默认:hh:mm:ss.fraction
tcpdump -nn -i eth0

# 完整日期 + 时间
tcpdump -nn -tttt -i eth0

# Unix 时间戳
tcpdump -nn -tt -i eth0

# 与上一个包的时间差
tcpdump -nn -ttt -i eth0

# 与第一个包的时间差
tcpdump -nn -ttttt -i eth0

# 不显示时间戳
tcpdump -nn -t -i eth0

# 显示包序号
tcpdump -nn --number -i eth0

十、生产环境最佳实践

10.1 黄金法则

生产抓包四步法:

1. 指定接口(-i any 如果不确定)
2. 加 -nn 禁止名字解析(避免卡顿)
3. 用 BPF 过滤收窄到关心的主机/端口/协议
4. 要么实时看,要么 -w 写 pcap 后用 Wireshark 分析

10.2 性能优化

性能问题与解决方案:

问题解决方案
丢包使用更精确的 BPF 过滤;-B 增大内核缓冲区;写入更快的磁盘
pcap 文件过大更精确过滤;-s 限制抓包长度;-C 按大小轮转
CPU 占用高避免 -A/-X 实时输出;用 -w 写文件不打印;内核层 BPF 过滤
磁盘写满-C + -W 环形缓冲;监控磁盘空间
# 增大内核缓冲区到 4096 KiB(减少丢包)
tcpdump -B 4096 -nn -i eth0 -w capture.pcap

# 打开设备后降权到 nobody(安全实践)
tcpdump -Z nobody -nn -i eth0 -w capture.pcap

# timeout 配合 tcpdump,防止忘关
timeout 60 tcpdump -nn -i eth0 -w /tmp/capture.pcap

10.3 抓包策略模板

# ===== 快速排查(实时终端)=====
tcpdump -nn -c 100 -i eth0 'host 10.0.0.50 and port 443'

# ===== 事件响应(完整抓包)=====
tcpdump -nn -s 0 -i eth0 -w incident_$(date +%Y%m%d_%H%M%S).pcap \
  'host 10.0.0.50 and (port 80 or port 443)'

# ===== 长期监控(轮转 + 压缩)=====
tcpdump -nn -s 0 -i eth0 -G 3600 -W 24 \
  -w '/var/captures/hourly_%H.pcap' \
  -z gzip \
  'net 10.0.0.0/8'

# ===== 高流量抓包(大缓冲 + 写快速磁盘)=====
tcpdump -nn -s 0 -i eth0 -B 4096 -w highspeed.pcap 'tcp port 443'

# ===== 容器流量(Docker)=====
tcpdump -nn -i docker0
tcpdump -nn -i br-XXXXXXXXXXXX

10.4 常见踩坑

踩坑点解决方案
tcpdump 无输出-D 检查接口名;确认有 root 权限
-i any 看不到 VLAN 标签改用具体物理接口抓包
-w 后终端无输出这是设计行为,需要双路输出用管道方案
Shell 解析了 &、`()`
旧版默认 snaplen 太小始终加 -s 0 确保全量抓取
DNS 解析导致卡顿始终加 -nn

十一、学习路线图

┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│  入门     │───▶│  进阶     │───▶│  高级     │───▶│  实战     │───▶│  专家     │
│          │    │          │    │          │    │          │    │          │
│ 基本抓包  │    │ BPF组合   │    │ 字节偏移  │    │ 生产排障  │    │ 自动化脚本 │
│ host/port│    │ and/or/not│    │ proto[]  │    │ pcap分析  │    │ 定时+告警  │
└──────────┘    └──────────┘    └──────────┘    └──────────┘    └──────────┘

各阶段目标与练习内容:

阶段目标练习内容
入门掌握基本抓包tcpdump -i any -nn,加 host/port 过滤
进阶BPF 逻辑组合and/or/not 组合,TCP 标志位
高级协议头部字段proto[offset:size] 字节偏移过滤
实战生产排障保存 pcap + Wireshark 分析,轮转抓包
专家自动化脚本tcpdump 配合 shell 脚本,定时抓包告警

十二、速查表

# ===== 基础 =====
tcpdump -D                                    # 列出接口
tcpdump -i any -nn                            # 监听所有接口,不解析
tcpdump -i eth0 -nn -c 100                    # 抓 100 个包

# ===== 过滤 =====
tcpdump -nn host 10.0.0.1                     # 指定主机
tcpdump -nn port 80                           # 指定端口
tcpdump -nn tcp                               # 指定协议
tcpdump -nn 'host 10.0.0.1 and port 443'      # 组合

# ===== TCP 标志 =====
tcpdump -nn 'tcp[tcpflags] & tcp-syn != 0'   # SYN
tcpdump -nn 'tcp[tcpflags] & tcp-rst != 0'   # RST
tcpdump -nn 'tcp[tcpflags] & tcp-fin != 0'   # FIN

# ===== 保存/读取 =====
tcpdump -nn -w file.pcap                      # 保存
tcpdump -nn -r file.pcap                      # 读取
tcpdump -nn -r file.pcap 'port 80'            # 读取并过滤

# ===== 输出格式 =====
tcpdump -nn -A 'port 80'                      # ASCII(HTTP)
tcpdump -nn -X                                # 十六进制+ASCII
tcpdump -nn -vvv                              # 最详细
tcpdump -nn -e                                # 含 MAC 地址

总结

本文核心要点:

  1. -nn 是第一原则:生产环境永远加 -nn,避免 DNS 反解导致卡顿
  2. BPF 过滤在内核生效:先过滤再抓包,而不是抓全量再过滤,高流量下差异巨大
  3. TCP 标志位是排障利器tcp[tcpflags] 语法精准抓取 SYN/RST/FIN,快速定位连接问题
  4. 字节偏移解锁高级场景proto[offset:size] 语法可匹配 HTTP 载荷、IP 头字段、ICMP 类型等
  5. 生产抓包写文件,离线分析-w 保存 pcap,用 Wireshark 或 tcpdump -r 事后分析

📌 官方文档


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值