tcpdump抓包分析实战:从入门到精通,运维必备的"网络显微镜"
凌晨2点,线上服务突然告警,业务反馈接口超时。监控显示服务正常,防火墙没动,配置也没改。你登服务器查了半天,越查越懵——网络明明是通的,业务就是跑不起来。
这种场景我太熟悉了,ping、telnet、netstat 这些老伙计轮番上场,问题依旧悬而未决。最后往往是抓个包一看,才发现是某个TCP重传、或者某个SYN被默默丢弃了。
今天这篇,把tcpdump的实战用法彻底讲清楚。文章比较长,建议先收藏,需要的时候翻出来对照着练。
认识tcpdump:为什么它这么重要
tcpdump是Linux下最经典的网络抓包工具,它工作在网络层,能捕获所有流经网卡的数据包。
和wireshark相比,tcpdump是命令行工具,更适合在服务器上直接使用,尤其是在没有图形界面的生产环境中,几乎是唯一选择。
我一直把它比作"网络显微镜"——ping只能告诉你通不通,telnet只能告诉你端口开没开,而tcpdump能让你看到每一个数据包的真实面貌。这在排查疑难网络问题时,往往是决定胜负的关键。
基础环境准备
开始之前,先准备两台虚拟机,配置如下:
| 主机 | IP | 系统 |
|---|---|---|
| rocky-web(服务端) | 192.168.159.167 | Rocky Linux 9 |
| rocky-client(客户端) | 192.168.159.168 | Rocky Linux 9 |
安装tcpdump很简单:
# CentOS/RHEL/Rocky
yum install -y tcpdump
# Ubuntu/Debian
apt-get install -y tcpdump必会的10个核心命令
1. 抓取指定网卡的包
最基础的用法,指定网卡开始抓包:
tcpdump -i ens160执行后会一直抓取该网卡上的所有流量,按Ctrl+C停止。刚接触tcpdump的同学会一脸懵——屏幕上刷刷刷地滚,根本看不清啥是啥。
别急,下面这些过滤参数会帮你精准定位。
2. 抓取指定数量的包
抓几个包看看就行:
tcpdump -c 5 -i ens160-c 5 表示只抓5个包就停止,避免一直刷屏看不清。
3. 不解析域名和端口(强烈推荐)
tcpdump -nn -i ens160nn参数告诉tcpdump不要把IP解析成域名、把端口解析成服务名。这一条在生产环境几乎必加,原因有两个:一是提升性能,避免DNS查询拖慢抓包;二是显示更直观,看到的端口号就是真实的端口号。
4. 显示完整时间戳
tcpdump -tttt -i ens160默认时间显示是11:34:19.760275这种只有时分秒的格式,加了-tttt后会变成2025-06-03 13:53:09.891524,排查问题时能精确到毫秒。
5. 指定协议类型
# 只抓ARP包
tcpdump -i ens160 arp
# 只抓TCP包
tcpdump -i ens160 tcp
# 只抓UDP包
tcpdump -i ens160 udp
# 只抓ICMP包(ping用的就是这个协议)
tcpdump -i ens160 icmp排查不同类型的问题,用不同的协议过滤,能极大减少干扰信息。
6. 指定端口
# 抓取80端口的包
tcpdump -i ens160 port 80
# 抓取多个端口
tcpdump -i ens160 'port 80 or port 443'
# 抓取端口范围
tcpdump -i ens160 portrange 8000-9000注意多条件要用引号包起来,避免shell解析出错。
7. 指定主机(最常用)
# 抓取和特定IP相关的所有包
tcpdump -i ens160 host 192.168.159.168
# 只抓源IP是该IP的包
tcpdump -i ens160 src host 192.168.159.168
# 只抓目标IP是该IP的包
tcpdump -i ens160 dst host 192.168.159.1688. 组合过滤(实战核心)
单个条件往往不够用,需要组合:
# 抓取从168到167的80端口请求
tcpdump -i ens160 src host 192.168.159.168 and dst host 192.168.159.167 and port 80
# 抓取特定网段
tcpdump -i ens160 net 192.168.159.0/24
# 排除某IP的流量
tcpdump -i ens160 not host 192.168.159.1支持的逻辑运算符有三个:and、or、not,组合起来能应对绝大多数场景。
9. 保存到文件(必备技能)
# 保存到pcap文件
tcpdump -i ens160 -w capture.pcap
# 抓100个包就停止
tcpdump -i ens160 -c 100 -w capture.pcap
# 指定端口保存
tcpdump -i ens160 port 80 -w http.pcap-w参数把原始数据包保存成pcap格式的文件,这个文件可以下载到本地用wireshark打开分析。pcap是抓包分析领域的通用格式,相当于网络流量的"录像"。
生产环境抓包时,建议先保存到文件,不要直接在终端看。原因很简单:终端刷屏太快根本看不清,而且文件可以反复回看。
10. 读取pcap文件
tcpdump -r capture.pcap
tcpdump -r capture.pcap host 192.168.159.168-r参数用于读取之前保存的pcap文件,可以加上过滤条件做精确分析。这个功能在排查历史问题、回溯故障时特别有用。
进阶用法:看懂的"钥匙"
光会抓还不够,还要看得懂抓出来的内容。下面我用一个真实场景,把包的结构讲透。
场景:抓取HTTP请求
在167上部署nginx,修改index.html:
<!DOCTYPE html>
<html>
<head>
<title>Test!</title>
</head>
<body>
<p><em>Hello the cruel world.</em></p>
</body>
</html>在168上发起请求:
while true; do curl 192.168.159.167; sleep 3; done在167上抓包:
tcpdump -i ens160 -nn -tttt -vvv dst 192.168.159.168 and port 80参数说明:
-nn:不解析域名和端口-tttt:显示完整时间戳-vvv:显示最详细的信息
抓出来的包长这样:
2025-06-03 16:41:03.735170 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)
192.168.159.167.80 > 192.168.159.168.48312: Flags [S.], cksum 0xc0cf (incorrect -> 0xf152), seq 1443628272, ack 853270288, win 31856, options [mss 1460,sackOK,TS val 1359281735 ecr 197104783,nop,wscale 7], length 0我来拆解一下这段信息到底在说啥:
- 时间戳:2025-06-03 16:41:03.735170
- 协议类型:IP(IPv4)
- TOS字段:0x0(服务类型)
- TTL:64(生存时间,每经过一个路由器减1)
- 包ID:0
- 标志位:
[DF]表示不分片 - 协议:TCP (6)
- 包长度:60字节
源地址到目标地址这一段:
192.168.159.167.80 > 192.168.159.168.48312意思是167的80端口,发往168的48312端口。> 代表数据流向。
Flags [S.] 是最关键的部分——这是TCP标志位:
S= SYN(建立连接).= ACK(确认)P= PSH(推送数据)F= FIN(关闭连接)R= RST(重置连接)
[S.] 表示这是SYN+ACK包,是TCP三次握手的第二阶段。
后面跟着 seq 1443628272(序列号)、ack 853270288(确认号)、win 31856(窗口大小)等,这些是TCP协议的核心字段。
抓取完整HTTP内容
想看到HTTP请求和响应的明文内容,用-X参数:
tcpdump -i ens160 -nn -tttt -XX dst 192.168.159.168 and port 80-X参数会以十六进制和ASCII两种形式显示包内容,能直接看到HTTP协议头:
HTTP/1.1 200 OK
Server: Tengine/3.1.0
Date: Tue, 03 Jun 2025 08:41:03 GMT
Content-Type: text/html
Content-Length: 121
Last-Modified: Tue, 03 Jun 2025 08:05:59 GMT
Connection: keep-alive是不是很神奇?连HTTP响应头都能完整看到。HTTPS是加密的看不到,但HTTP的明文内容能看个底朝天——这也是为什么HTTP不适合传输敏感信息。
实战案例:TCP三次握手分析
理解TCP三次握手是看包的基础。我把一个完整的HTTP请求包序列拆解一下:
1. 192.168.159.167.80 > 192.168.159.168.48312: Flags [S.], seq X, ack Y+1 # 第二次握手
2. 192.168.159.167.80 > 192.168.159.168.48312: Flags [.], ack Y+1 # 第三次握手
3. 192.168.159.167.80 > 192.168.159.168.48312: Flags [P.], seq 1:239 # 发送数据
4. 192.168.159.167.80 > 192.168.159.168.48312: Flags [F.], seq 360 # 关闭连接注意这里没有第一次握手,因为用的是dst 192.168.159.168,过滤的是发给168的包,第一次握手是168发给167的。
完整的TCP连接生命周期:
- SYN → 客户端请求建立连接
- SYN+ACK → 服务端同意建立
- ACK → 客户端确认
- PSH+ACK → 传输数据
- FIN+ACK → 关闭连接
故障信号识别:
- 只有SYN没有SYN+ACK → 服务端无响应(端口未开/防火墙拦截)
- 大量SYN+无ACK → 可能是SYN Flood攻击
- 大量TCP重传(Retransmission)→ 网络丢包严重
- RST包异常增多 → 端口被强制关闭
高级过滤:按标志位抓包
按TCP标志位过滤是排查特定问题的高级技巧:
# 只抓SYN包(排查SYN Flood)
tcpdump -i ens160 'tcp[tcpflags] & tcp-syn != 0'
# 只抓SYN+ACK包
tcpdump -i ens160 'tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)'
# 只抓RST包(排查异常重置)
tcpdump -i ens160 'tcp[tcpflags] & tcp-rst != 0'
# 抓SYN但排除SYN+ACK
tcpdump -i ens160 'tcp[tcpflags] & tcp-syn != 0 and not tcp[tcpflags] & tcp-ack'syn_flood攻击的特征就是短时间内大量SYN包但没有对应的ACK,用这个过滤条件能快速识别。
真实故障案例:防火墙导致服务不通
某天收到反馈,访问Web服务提示"无法连接服务器",但服务端进程正常。常规检查全部正常,就是连不上。
用tcpdump在服务端抓包:
tcpdump -i eth0 port 8080 -w web_capture.pcap下载到本地用wireshark分析,发现客户端SYN包已经到了服务端,但服务端没有任何响应。
同步在客户端抓包,看到客户端一直在重传SYN(1s → 2s → 4s 指数退避),最终超时。
最后查防火墙规则,发现有人加了这条:
iptables -A INPUT -p tcp --dport 8080 -j DROP防火墙把8080端口的包默默丢弃了,连个RST都不回,所以客户端只能干等。临时删除规则后,TCP三次握手瞬间正常。
这个案例给我的启示是:用tcpdump能"看到"网络层到底发生了什么,比靠猜要靠谱得多。ping和telnet只能告诉你表象,抓包才能看到真相。
配合Wireshark做深度分析
tcpdump在服务器上抓包很方便,但分析起来不如wireshark直观。最佳实践是:用tcpdump抓包保存成pcap文件,下载到本地用wireshark分析。
wireshark的几个神仙功能:
1. Follow TCP Stream(追踪TCP流)
右键 → Follow → TCP Stream,能把一次TCP会话的所有数据按顺序完整展示出来,不用自己拼接。
2. 过滤器语法
wireshark的过滤器比tcpdump更强大,比如:
# 只看重传
tcp.analysis.retransmission
# 只看丢包
tcp.analysis.lost_segment
# 只看乱序
tcp.analysis.out_of_order
# 只看RST
tcp.flags.reset == 13. Statistics → Conversations
看所有会话的统计信息,包括包数、字节数、重传率,一眼就能定位异常会话。
生产环境抓包的注意事项
最后说几个容易踩的坑,都是我用血泪换来的经验:
1. 抓包会消耗CPU
高流量场景下抓包非常消耗CPU资源,建议在低峰期抓,或者用-c限制包数量。
2. 磁盘空间要预留
一个高流量的pcap文件可能几分钟就几个G,抓包前先df -h看看磁盘。我曾经因为没注意磁盘,pcap文件把根分区撑爆,机器直接挂了。
3. 多网卡机器要指定网卡
服务器一般有多块网卡(业务网卡、管理网卡、存储网卡),用-i指定正确的网卡,不然可能抓到一堆无关流量。
4. 权限问题
tcpdump需要root权限或CAP_NET_RAW能力。普通用户执行会报permission denied。
5. 容器内抓包要特殊处理
在K8s容器里抓包比较麻烦,常见做法是用kubectl debug注入一个带tcpdump的临时容器,官方文档有详细的操作步骤。
6. 大文件用-W和-C切割
# 每个文件100MB,最多保留10个文件
tcpdump -i eth0 -w capture.pcap -C 100 -W 10-C 100表示每个文件100MB,-W 10表示最多保留10个文件,避免磁盘被撑爆。
7. 性能优化参数
# 增大缓冲区到2MB
tcpdump -i eth0 -B 2048 port 80
# 抓完整包(不截断)
tcpdump -i eth0 -s 0 port 80默认-s 0只抓每个包的前68字节,看不到完整内容。用-s 0抓完整包,虽然更耗资源,但能看到所有细节。
我的tcpdump常用命令速查
最后整理一份我日常用得最多的命令清单,建议保存:
# 1. 基础抓包
tcpdump -i eth0 # 抓所有包
tcpdump -i eth0 -nn # 不解析域名端口
tcpdump -i eth0 -c 100 # 只抓100个包
tcpdump -i eth0 -tttt # 显示完整时间戳
# 2. 按条件过滤
tcpdump -i eth0 host 192.168.1.1 # 指定主机
tcpdump -i eth0 port 80 # 指定端口
tcpdump -i eth0 tcp # 指定协议
tcpdump -i eth0 'port 80 and host 192.168.1.1' # 组合条件
# 3. 文件操作
tcpdump -i eth0 -w file.pcap # 保存到文件
tcpdump -r file.pcap # 读取文件
tcpdump -i eth0 -w file.pcap -C 100 -W 5 # 文件切割
# 4. 高级过滤
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0' # SYN包
tcpdump -i eth0 'tcp[tcpflags] & tcp-rst != 0' # RST包
# 5. 显示详细信息
tcpdump -i eth0 -v # 详细
tcpdump -i eth0 -vv # 更详细
tcpdump -i eth0 -vvv # 最详细
tcpdump -i eth0 -X # 显示包内容(十六进制+ASCII)
tcpdump -i eth0 -s 0 -X # 显示完整包内容结语
tcpdump看着简单,但真要用好,需要大量的实战积累。建议大家搭个测试环境,亲手抓一下各种场景的包:
- 正常HTTP请求的包长啥样
- TCP三次握手的完整过程
- 四次挥手的包序列
- 连接被重置时的RST包
- 网络丢包时的重传包
看多了,下次遇到问题就能一眼看出包里的异常。抓包分析能力,是运维工程师的核心竞争力之一,也是面试的高频考点。
如果觉得本文有用,欢迎点赞、在看、转发三连,让更多运维兄弟看到。
关注公众号【耕云躬行录】,回复"tcpdump"领取我整理的tcpdump速查手册(含常用命令、过滤表达式、故障排查清单)。
个人博客:躬行笔记