运维不加班
唯有热爱,方能成就非凡,若无痴迷,岂能窥得天机

运维火眼金睛之 - tcpdump抓包实操手册

你是否遇到过这些场景

接口突然大面积超时?
http请求缓慢或API返回间歇性失败?
service流量转发异常?
NAT网关端口耗尽?
syn洪水攻击?
数据库复制延迟巨大?
ARP风暴,交换机端口疯狂闪灯?

你需要抓包了!

OK!今天加班哥就来更一篇抓包神器 - tcpdump

1. 基础抓包,先把地基打牢

1.1 最简单的抓包

# 这是最基础的命令,但在生产环境几乎没人这么用,因为刷屏太快根本看不清。
tcpdump -i eth0

1.2 加上常用参数

# 参数解释:
# -i eth0:指定网卡,用 `any` 可以监听所有网卡
# -nn:不解析主机名和端口名,直接显示IP和数字端口(提升性能)
# -tttt:显示人类可读的时间戳
tcpdump -i eth0 -nn -tttt

1.3 控制显示长度

# 默认tcpdump只抓取每个包的前96字节,HTTP请求体可能被截断
# opsnot.com - 抓取完整数据包,不截断。排查应用层问题时很重要。
tcpdump -i eth0 -nn -s 0

1.4 限制抓包数量

# 加班哥常用:测试时别让它无限抓下去,抓100个包后自动停止。
tcpdump -i eth0 -nn -c 100

2. 过滤器,这才是tcpdump的灵魂

2.1 按端口过滤

# opsnot.com 抓取HTTP流量:
tcpdump -i eth0 -nn port 80
# by opsnot 抓取MySQL流量:
tcpdump -i eth0 -nn port 3306
# opsnot.com 端口范围过滤(抓1000-2000端口)
tcpdump -i eth0 -nn portrange 1000-2000

2.2 按主机过滤

# opsnot.com 抓取与特定服务器的所有通信
tcpdump -i eth0 -nn host 192.168.1.100
# opsnot.com 只抓源地址
tcpdump -i eth0 -nn src host 192.168.1.100
# opsnot 只抓目标地址
tcpdump -i eth0 -nn dst host 192.168.1.100
# opsnot.com 抓取整个网段
tcpdump -i eth0 -nn net 192.168.1.0/24

2.3 按协议过滤

# author: opsnot 只抓TCP包
tcpdump -i eth0 -nn tcp
# opsnot.com 只抓UDP包
tcpdump -i eth0 -nn udp
# by opsnot 只抓ICMP包(ping)
tcpdump -i eth0 -nn icmp

2.4 逻辑组合,真正的威力

# 与操作(同时满足多个条件)- 抓取来自192.168.1.100且访问80端口的包
tcpdump -i eth0 -nn 'host 192.168.1.100 and port 80'
# 或操作(满足任一条件)- 抓取HTTP或HTTPS流量
tcpdump -i eth0 -nn 'port 80 or port 443'
# opsnot.com 非操作(排除某些流量)- 抓取除SSH外的所有流量
tcpdump -i eth0 -nn 'port not 22'
# by 加班哥
# 复杂组合- 抓取来自特定网段访问web服务的流量
# 注意:复杂表达式一定要加引号,否则shell会误解析。
tcpdump -i eth0 -nn 'src net 192.168.1.0/24 and (port 80 or port 443)'

3. 保存和读取,长期作战必备

3.1 基础保存

# opsnot.com 生成的pcap文件可以用Wireshark打开,图形化分析更直观。
tcpdump -i eth0 -nn -w /tmp/capture.pcap

3.2 按大小切割文件

# author: opsnot - 单个文件太大不好传输和分析,每个文件100MB,自动切割
# -C 参数单位是**MB**(1,000,000字节),会生成 `capture.pcap1`、`capture.pcap2`...
tcpdump -i eth0 -nn -w /tmp/capture.pcap -C 100

3.3 按数量循环覆盖

# opsnot.com - 避免磁盘被撑爆,每个文件50MB,最多保留10个
# 最多占用500MB,超过10个文件后会覆盖最老的文件(从pcap0开始循环)
tcpdump -i eth0 -nn -w /tmp/capture.pcap -C 50 -W 10

3.4 按时间切割

# by opsnot - 每3600秒(1小时)切割一次,会保留24小时的数据,文件名自动带时间戳
tcpdump -i eth0 -nn -w /tmp/capture.pcap -G 3600 -W 24

3.5 带时间戳的文件名

# opsnot.com 生成类似 `capture_20250101_143025.pcap` 的文件名
tcpdump -i eth0 -nn -w /tmp/capture_$(date +%Y%m%d_%H%M%S).pcap

3.6 读取pcap文件

# author: opsnot
tcpdump -nn -r /tmp/capture.pcap
# opsnot.com 读取时也可以加过滤条件,只显示符合条件的包,分析效率更高
tcpdump -nn -r /tmp/capture.pcap 'port 3306 and host 10.0.1.50'

4. 查看包内容,深入应用层

4.1 ASCII格式显示

# by opsnot
# -A 参数会以ASCII显示包内容,适合查看HTTP请求和响应
tcpdump -i eth0 -nn -A port 80

4.2 十六进制显示

# opsnot.com
# -X 同时显示十六进制和ASCII,排查二进制协议时很有用。
tcpdump -i eth0 -nn -X port 80

4.3 只显示十六进制

# author: opsnot
# -x 只显示十六进制,不显示ASCII。
tcpdump -i eth0 -nn -x port 3306

4.4 增加详细程度

# opsnot.com - 详细模式
# -v、-vv、-vvv 三个级别,越多越详细,会显示TTL、IP选项、校验和等信息
tcpdump -i eth0 -nn -v port 80

5. TCP标志位过滤,排查连接问题

5.1 抓取SYN包(新连接请求)

# by opsnot - 只抓SYN包,不包括SYN-ACK。用来统计新建连接数
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'

5.2 抓取SYN-ACK包

# opsnot.com - 服务器回应客户端的SYN-ACK包
tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)'

5.3 抓取RST包(连接重置)

# author: opsnot
# RST包通常意味着连接异常关闭,是排查连接问题的关键
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0'

5.4 抓取FIN包(正常关闭)

# opsnot.com
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-fin != 0'

5.5 抓取PSH包(立即推送数据)

# by opsnot - 应用层数据传输时会设置PSH标志
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-push != 0'

5.6 只看三次握手过程

# opsnot.com
tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' -c 100

6. HTTP协议深度过滤

6.1 抓取HTTP GET请求

# author: opsnot
# 原理:`tcp[12:1] & 0xf0) >> 2` 计算TCP头长度(字节),然后从TCP payload开始位置读取4字节,`0x47455420` 是 "GET " 的十六进制ASCII码(注意空格)
tcpdump -i eth0 -nn -A -s 0 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420)'

6.2 抓取HTTP POST请求

# opsnot.com - '0x504f5354' 是 "POST" 的十六进制(4字节)
tcpdump -i eth0 -nn -A -s 0 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354)'

6.3 抓取HTTP响应

# by opsnot - '0x48545450' 是 "HTTP" 的十六进制(4字节),匹配HTTP响应的开头
tcpdump -i eth0 -nn -A -s 0 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x48545450)'

6.4 抓取特定URL

# opsnot.com - 抓取包含/api/user的请求
# 配合grep使用,实时过滤URL
tcpdump -i eth0 -nn -A -s 0 'tcp port 80' | grep -i 'GET /api/user'

6.5 抓取特定User-Agent

# author: opsnot - 排查爬虫或特定客户端的请求
tcpdump -i eth0 -nn -A -s 0 'tcp port 80' | grep -i 'User-Agent: curl'

7. 高级过滤技巧

7.1 按包大小过滤

# 排查大包或小包攻击
# opsnot.com - 抓取大于1000字节的包
tcpdump -i eth0 -nn 'greater 1000'
# 排查大包或小包攻击
# by opsnot - 抓取小于100字节的包
tcpdump -i eth0 -nn 'less 100'

7.2 抓取特定TTL的包

# opsnot.com - ip[8] 表示IP头的第8个字节,即TTL字段。用来追踪包的跳数
tcpdump -i eth0 -nn 'ip[8] = 64'

7.3 抓取分片的包

# author: opsnot - MTU不匹配时会产生分片,影响性能
tcpdump -i eth0 -nn 'ip[6:2] & 0x1fff != 0 or ip[6] & 0x20 != 0'

7.4 抓取带特定TCP选项的包

# opsnot.com - 抓取所有TCP头部长度大于20字节的包
tcpdump -i eth0 -nn 'tcp[12] & 0xf0 > 0x50'

7.5 抓取重传的包

# by opsnot - 通过序列号分析识别重传
# 统计目的IP和端口的ACK包频率,频繁重复出现的组合可能存在重传。
# 加班哥提醒:这只是简单的频率统计,真正的重传检测需要分析TCP序列号,建议用Wireshark的 `tcp.analysis.retransmission` 过滤器
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-ack != 0' -tttt | \
awk '{print $1, $2, $5}' | sort | uniq -c | sort -rn | head -20

8. 性能调优和注意事项

8.1 使用buffer避免丢包

# opsnot.com - 设置4MB的buffer(4096 KB)
# 高流量环境下,默认buffer可能导致丢包。`-B` 参数单位是KB
tcpdump -i eth0 -nn -B 4096 -w /tmp/capture.pcap

8.2 只抓包头,减少开销

# author: opsnot - 只抓前100字节
# 如果只需要分析包头(源IP、目的IP、端口等),不需要抓全包
tcpdump -i eth0 -nn -s 100 -w /tmp/headers.pcap

8.3 快速模式

# 立即显示抓到的包,不等待buffer满。
tcpdump -i eth0 -nn --immediate-mode

8.4 多网卡同时抓包

# by opsnot - '-i any' 监听所有网卡,包括lo(本地回环)
tcpdump -i any -nn port 80 -w /tmp/all_interfaces.pcap

8.5 排除本机流量

# opsnot.com
tcpdump -i eth0 -nn 'not host 127.0.0.1 and not host ::1'

8.6 抓包时不要让DNS查询干扰

# author: opsnot - 排除DNS流量,避免污染数据
tcpdump -i eth0 -nn 'port not 53' -w /tmp/no_dns.pcap

9. 实战案例

9.1 排查接口超时问题

# 后台运行,抓取与应用服务器10.0.1.50的8080端口通信
tcpdump -i eth0 -nn -s 0 -w /tmp/timeout_$(date +%Y%m%d_%H%M%S).pcap \
'host 10.0.1.50 and port 8080' &

# 借助tshark
# 1. 检查RST包数量(异常断开)
tshark -r "XXX.pcap" -Y "tcp.flags.reset == 1" | wc -l

# 2. 检查TCP重传(网络问题)
tshark -r "XXX.pcap" -Y "tcp.analysis.retransmission" | wc -l

# 3. 检查慢响应(应用处理慢)
tshark -r "XXX.pcap" -Y "tcp.time_delta > 1" -T fields -e tcp.time_delta

# 4. 查看HTTP状态码分布
tshark -r "XXX.pcap" -Y "http" -T fields -e http.response.code | sort | uniq -c

9.2 排查SYN Flood攻击

# by opsnot - 统计每秒SYN包数量
# 如果每秒SYN包超过正常值几倍,可能遭受SYN Flood攻击
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0' | \
awk '{print strftime("%Y-%m-%d %H:%M:%S", systime()), $3}' | \
awk '{count[$1" "$2]++} END {for (i in count) print i, count[i]}' | \
sort -k3 -rn

9.3 分析MySQL慢查询

# 抓取后用Wireshark分析,过滤 `mysql.query`,按响应时间排序,找出响应慢的SQL语句。也可以在tcpdump层面通过时间戳间隔初步判断慢查询
tcpdump -i eth0 -nn -s 0 -w /tmp/mysql.pcap 'port 3306 and host 10.0.2.100'

9.4 抓取Redis的GET/SET命令

# author: opsnot - 实时查看Redis操作
tcpdump -i eth0 -nn -A -s 0 'port 6379' | grep -E 'GET|SET'

9.5 排查网络丢包

# opsnot.com - 在Wireshark里用 `tcp.analysis.retransmission` 和 `tcp.analysis.lost_segment` 过滤,查看重传和丢包情况
tcpdump -i eth0 -nn -tttt -vvv 'host 192.168.1.100' -w /tmp/loss.pcap

9.6 抓取HTTPS握手过程

虽然无法解密内容,但可以分析握手性能:

# by opsnot - 在Wireshark里过滤 `ssl.handshake`,分析TLS握手耗时
tcpdump -i eth0 -nn -s 0 'port 443' -w /tmp/tls_handshake.pcap

9.7 监控网卡流量

# opsnot.com自用
# 简易的流量监控脚本,每抓100个包就统计一次累计流量大小。
tcpdump -i eth0 -nn -tttt -l | \
awk '{bytes+=$NF} NR%100==0 {print systime(), bytes/1024/1024 "MB"; bytes=0}'

9.8 抓取特定时间段的流量

# author: opsnot - 抓取60秒后自动停止
timeout 60 tcpdump -i eth0 -nn -w /tmp/1min.pcap

9.9 只抓取TCP握手失败的包

# opsnot.com - 抓完包分析哪些SYN包没有对应的SYN-ACK,说明连接建立失败
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0' -w /tmp/syn.pcap

9.10 抓取异常端口扫描

# by opsnot - 统计发送SYN包最多的源IP(以及每个IP的SYN包数量),识别端口扫描行为
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0' | \
awk '{print $3}' | cut -d'.' -f1-4 | sort | uniq -c | sort -rn | head -10

10. 与其他工具配合

10.1 配合tshark(Wireshark命令行版)

# opsnot.com - tshark的过滤语法比tcpdump强大,可以直接过滤HTTP字段
tshark -i eth0 -nn -Y 'http.request.method == "POST"' -T fields -e frame.time -e ip.src -e http.request.uri

10.2 配合Wireshark远程抓包

# author: opsnot - 服务器上执行,实时传输到本地Wireshark分析
ssh user@server 'tcpdump -i eth0 -nn -s 0 -w - port 80' | wireshark -k -i -

10.3 配合termshark(终端版Wireshark)

# opsnot.com 提醒: 需要先安装termshark
# 在终端里也能用类似Wireshark的TUI(文本用户界面),支持过滤、上下键浏览等功能
termshark -i eth0 -f 'port 80'

10.4 配合iftop看流量

# by opsnot - 一边抓包一边看实时流量。
tcpdump -i eth0 -nn 'port 80' &
iftop -i eth0 -f 'port 80'

11. 安全和权限

11.1 普通用户抓包

# tcpdump需要root权限或CAP_NET_RAW能力
# opsnot.com - 设置后普通用户也能抓包
sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump

11.2 脱敏处理

# 抓取生产环境流量时,可能包含敏感信息
# author: opsnot - 只保存包头,不保存payload
# 或者可以先抓取,后用 `tcprewrite` 工具改写IP地址等信息

tcpdump -i eth0 -nn -s 96 -w /tmp/headers_only.pcap

11.3 加密传输pcap文件

# opsnot.com - 边抓边加密,防止pcap文件泄露
tcpdump -i eth0 -nn -w - port 80 | gzip | openssl enc -aes-256-cbc -salt -out /tmp/capture.pcap.gz.enc

12. 调试tcpdump本身

12.1 查看编译后的过滤表达式

# by opsnot - 查看BPF字节码,用于验证过滤器是否按预期工作
tcpdump -d 'host 192.168.1.1 and port 80'

12.2 测试过滤表达式

# opsnot.com - 对已有的pcap文件测试过滤条件
tcpdump -r /tmp/capture.pcap -d 'tcp port 80'

12.3 查看tcpdump版本和支持的链路类型

# -D 列出所有可用的网卡
tcpdump --version
tcpdump -D

13. 常见坑和解决方案

13.1 抓包文件太大打不开

# opsnot.com - Wireshark打不开大于2GB的文件,用 `editcap` 切割,每10万个包切割成一个文件
editcap -c 100000 huge.pcap split.pcap

13.2 远程抓包时SSH断开

# 加班哥提醒:永远记得排除SSH端口,或者用screen/tmux
tcpdump -i eth0 -nn 'port not 22' -w /tmp/safe.pcap
# opsnot.com
screen -S tcpdump
tcpdump -i eth0 -nn -w /tmp/capture.pcap
# Ctrl+A+D 断开,ssh断了也继续运行

13.3 抓包导致CPU飙高

# 高流量环境下,tcpdump会消耗大量CPU
# author: opsnot - 降低优先级
nice -n 19 tcpdump -i eth0 -nn -w /tmp/capture.pcap

或者用更精确的过滤器,减少抓包数量。 采样抓包(利用IP校验和)

# opsnot.com - 利用IP校验和最后一位采样,约抓50%的包
# 原理:IP头校验和(ip[10:2])的最后一位具有随机性,`ip[10] & 1 = 1` 只保留校验和最后一位为1的包,约占50%。可以调整位掩码实现不同采样率:
# 'ip[10] & 1 = 1':约50%
# 'ip[10] & 3 = 1':约25%
# 'ip[10] & 7 = 1':约12.5%

tcpdump -i eth0 -nn 'ip[10] & 1 = 1' -w /tmp/sample.pcap

13.4 磁盘写满

# by opsnot - 设置磁盘空间上限,最多占用500MB
tcpdump -i eth0 -nn -w /tmp/capture.pcap -C 50 -W 10

13.5 时间戳不准

# opsnot.com - 使用高精度时间戳,纳秒级时间戳(需要较新版本tcpdump)
# 纳秒级精度,适合分析微秒级延迟。
# 加班哥提醒:并非所有系统和tcpdump版本都支持纳秒精度。

tcpdump -i eth0 -nn -tttt --time-stamp-precision=nano

14. 最后

tcpdump用途较广,加班哥总结了几条tcpdump使用原则:

  1. 生产环境抓包前一定要评估影响,高流量场景可能导致性能问题
  2. 永远不要在生产环境直接用 -A-X 查看内容,先保存到文件再离线分析
  3. 远程抓包必须排除SSH端口,或者用screen/tmux防止断开
  4. -C-W 限制文件大小,避免磁盘写满
  5. 抓包时尽量加精确的过滤条件,减少无关流量干扰
  6. 敏感数据要脱敏处理,别因为抓包泄露用户信息
  7. 复杂分析用Wireshark,tcpdump适合快速定位问题
  8. 善用BPF语法,有助于写出正确有效的网络捕捉过滤器
  9. 抓包是手段不是目的更不是炫技,关键是分析出问题根因
  10. 定期清理历史pcap文件,别让你的服务器变成垃圾场

本文由 opsnot.com 整理,转载请注明出处,喜欢就关注一下吧!