资讯动态

tcpdump与Wireshark抓包全解:原理、实操与排障实战

发布时间:2026/9/10 0:22:00 来源:尧图企业网站定制
做后端开发和网络运维几乎都躲不过抓包这个活。之前有回遇到客户反馈“接口偶尔要跑10秒”代码层面全是超时重试日志翻了个遍也没头绪最后抓包一看TCP 重传了 5 次才缓过来问题一下就定位了。Linux 下抓包的核心组合其实很固定就是 tcpdump Wiresharktcpdump 负责把数据包从网卡上捞下来Wireshark 负责把报文拆开给你看中间用 pcap 文件对接。这篇就把抓包的原理、工具选型、常用操作、分析技巧和踩坑实录一次讲透从只会tcpdump -i eth0到能精准定位网络问题适合后端开发、运维、嵌入式工程师和对网络协议感兴趣的读者。1. 抓包之前先弄清数据包在哪里等着你1.1 数据包从网卡到应用的完整路径我们写的程序读到网络数据之前包其实已经跑完了一段“标准化旅程”。网卡硬件收到物理信号后把数据还原成帧Frame写入内核内存的环形缓冲区触发中断通知 CPU内核协议栈接着按链路层、网络层、传输层的顺序逐层解析最终把数据排队到对应 socket 的接收缓冲区应用调用read()/recv()才拿到 payload。抓包工具就藏在这条链路里。它通过AF_PACKETLinux 上的抓包专用套接字或libpcap库在数据链路层复制一份帧数据给自己完全不影响原包继续往上走。也就是说抓包是“旁路监听”不是“拦截”。你可以把它理解成教室门口装了监控摄像头它记录谁进谁出但并不拦下每个人检查学生证学生该上课上课该下课下课。这个特性极其重要意味着抓包本身通常不会影响业务流量。不过要特别留意抓包工具能看到的原始内容就是“网卡层次”的帧。所以抓包文件里能看到 MAC 地址、VLAN 标签、IP、端口、协议头还能看到应用层明文比如 HTTP 请求但如果流量是 HTTPS应用层已经加了 TLS 加密抓包默认只能看到 TLS 握手和密文看不到具体请求参数。这一点不搞清楚很容易抓了半天以为自己工具用错了。1.2 混杂模式、回环接口与流量可见范围网卡默认工作在非混杂模式硬件层只接收目的 MAC 地址是“自己”的帧以及广播帧和组播帧。如果我们想监听链路上所有机器的流量就得把网卡设为混杂模式Promiscuous Mode也就是让网卡把经过物理链路的所有帧都收上来。但这里有一个经常被误解的点在普通交换机网络里即使你开启了混杂模式也只能看到“经过你网卡”的流量交换机并不会把所有端口的数据都复制给你。想抓别人的包那是另一套玩法需要交换机端口镜像SPAN/ERSPAN或接入层旁路设备不是配置一个混杂模式就能搞定的。还有一个特殊的接口叫回环接口lo。当本机进程访问本机服务比如 curl 访问 localhost:8080时数据包根本不经过物理网卡而是直接在协议栈内部走捷径发送方把包交给 IP 层发现目的 IP 是 127.0.0.1直接又从 IP 层“回收”给接收方。这种情况下只要指定tcpdump -i lo一样可以抓到完整的网络层报文。新手做实验最方便的路径就是从 lo 开始抓看三次握手、看HTTP请求全在本机完成不需要任何额外的机器。1.3 抓包能看到哪些层对应什么问题抓包文件里的数据是按协议栈一层一层包裹的每层都有对应的分析价值协议层典型字段能定位什么问题链路层MAC地址、VLAN二层环路、广播风暴、帧格式异常网络层IP、TTL、分片标志路由错误、TTL超时、IP分片传输层端口、序号、窗口、标志位三次握手失败、重传、RST重置、拥塞应用层HTTP请求行、DNS域名接口超时、DNS解析慢、HTTP报错实际排查问题时80% 的情况看传输层就足够定位了。TCP 的 SYN、SYN-ACK、ACK、RST、重传、零窗口每一个标志都代表一种明确的状态变化。所以抓包分析先把 TCP 层搞明白收益最大。2. 工具选型解析不是所有抓包都叫 Wireshark2.1 tcpdump服务器上最可靠的常驻工具大多数 Linux 服务器是没有图形界面的Wireshark 这个带 GUI 的软件装上去也起不来。这时 tcpdump 就是唯一需要的工具。它由命令行驱动依赖极少在最小化安装的服务器上也能直接apt install -y tcpdump或yum install -y tcpdump装好。抓包、过滤、写文件、读文件一条命令全搞定。tcpdump 的性能也是非常优秀的。它的过滤表达式BPF即 Berkeley Packet Filter会先被编译成内核态字节码由内核里的一个“微型虚拟机”直接执行匹配失败的数据包根本不会拷到用户态所以在大流量环境下也能保持比较高的抓包效率。相比之下如果抓包工具在用户态做过滤要把所有包都从内核拷贝到应用层性能差距会非常大。这也是我坚持在生成环境首选 tcpdump 的原因它量级轻、不打扰适合现场排查和无人值守采集。2.2 Wireshark 和 TShark把 pcap 变成结论tcpdump 抓出来的 pcap 文件最好还是交给 Wireshark 分析。Wireshark 的强大之处不在于“抓”而在于“看”它能把 TCP 时序、重传、乱序、三段握手、应用层协议解析得一清二楚还按照协议类型自动着色异常包一眼就能挑出来。特别是排查“某个接口为什么慢”这类问题Wireshark 自带的 IO Graph 和 Flow Graph 能非常直观地展示哪个环节耗时最多。TShark 是 Wireshark 的命令行版本保留了大部分分析能力但没有图形界面。它特别适合批量处理大量 pcap 文件比如你有几十个抓包文件想提取所有的 HTTP 请求 URI、响应状态码或统计某个 IP 对端口的连接次数一条 tshark 命令加字段过滤就搞定了。如果只有一两个 pcap打开 Wireshark 鼠标点点更舒服如果要处理成百上千的文件tshark 才能救命。2.3 dumpcap 以及大流量采集方案如果你要做长时间、无人值守的抓包比如后台运行一整晚或者在高吞吐链路上采集样本推荐用 dumpcap。它是 Wireshark 团队维护的纯捕获工具只负责把包写到磁盘不做任何实时分析因此开销比 tcpdump 和 tshark 都小。dumpcap 支持按文件大小自动轮转-b filesize:10000即每个文件写到约10MB就切换新的文件并可以配合-n参数限制文件个数避免磁盘写满。工具选择的思路其实很简单先想清楚你的目标是现场快速看一下流量就 tcpdump是抓完拿回本地慢慢分析就 tcpdump 写文件 Wireshark 阅读是要自动化地从大量文件中提取信息就用 tshark是长期后台采集就用 dumpcap。不需要在服务器上装满满一屏工具够用才最好。工具界面主要用途典型命令tcpdumpCLI现场抓包、快速过滤tcpdump -i eth0 -nn port 80WiresharkGUIpcap深度分析、查看时序菜单操作tsharkCLI批量提取、脚本化分析tshark -r a.pcap -Y http.requestdumpcapCLI大流量长期抓包、文件轮转dumpcap -i eth0 -w /tmp/x.pcap -b filesize:102403. 核心实操tcpdump 从入门到够用3.1 基础命令与常用参数解读tcpdump 的参数不算多但每个都很关键。最常用的几个组合如下# 监听指定网卡只看 20 个包就自动退出 tcpdump -i eth0 -c 20 # 不解析主机名和端口名直接显示 IP 和数字端口 tcpdump -i eth0 -nn -c 20 # 把原始包抓到文件中供后续分析 tcpdump -i eth0 -nn -s 0 -w /tmp/capture.pcap # 读取刚才抓的 pcap 文件 tcpdump -r /tmp/capture.pcap逐个参数说-i指定网卡最常用的是具体网卡名eth0、ens33、enp0s3 等也可以填any表示监听系统上所有网卡在不确定流量走哪张卡时非常有用-c是抓多少个包后自动停止适合快速验证-nn表示不要对 IP 做反向 DNS 解析、也不要对端口做服务名映射直接显示数字。这个参数我强烈建议默认带上DNS 反解会耗时且可能发出大量 DNS 请求干扰抓包现场而且解析出来的域名往往没有实际价值。-s 0表示抓取整个数据包不限制长度。老版本的 tcpdump 默认可能只抓取前 96 字节或者几十字节只够看头部payload 被截断了现代版本虽然默认长度已经够大但为了保险起见抓包时建议显式写上-s 0否则后续分析时发现应用层数据被截断只能重新抓。-w和-r是写文件和读文件几乎所有正式排查流程都离不开这两个参数尤其推荐现场抓包直接写文件而不是把输出打印在屏幕上——终端打印本身也是一笔不小的性能开销。再看一条完整输出20:15:30.112345 IP 192.168.1.10.54320 192.168.1.1.80: Flags [S], seq 305419896, win 64240, options [mss 1460], length 0从左到右依次是时间、IP 协议、源地址.源端口、目的地址.目的端口、TCP 标志位、序号、窗口大小、TCP选项和载荷长度。Flags [S]表示这是 SYN 报文seq 305419896是客户端初始序号这些是分析握手和重传的基础信息。3.2 过滤表达式是核心中的核心tcpdump 的过滤语法官方叫pcap-filter是一种基于 BPF 的过滤规则。初学者最容易踩的坑就是把 tcpdump 的“捕获过滤器”和 Wireshark 里的“显示过滤器”混为一谈——两者语法完全不同。tcpdump 多数情况下在空格后面跟的就是过滤表达式# 只看某个主机的流量 tcpdump -i eth0 -nn host 192.168.1.10 # 只看某两个主机之间的流量 tcpdump -i eth0 -nn host 192.168.1.10 and host 192.168.1.20 # 只看源或目的端口 tcpdump -i eth0 -nn port 80 tcpdump -i eth0 -nn src port 80 tcpdump -i eth0 -nn dst port 80 # 端口范围 tcpdump -i eth0 -nn portrange 8000-9000 # 协议组合 tcpdump -i eth0 -nn tcp port 443 tcpdump -i eth0 -nn udp port 53 tcpdump -i eth0 -nn icmp逻辑运算符and、or、not可以组合嵌套复杂表达式可能包含括号所以建议整个表达式用单引号包起来防止 shell 做错误展开# 抓所有发给 1.1.1.1 的 TCP 80 端口包以及任意发往 2.2.2.2 的包 tcpdump -i eth0 -nn host 1.1.1.1 and tcp port 80 or host 2.2.2.2更进阶的玩法是直接做“字节偏移匹配”。比如只看 TCP SYN 包tcpdump -i eth0 -nn tcp[13] 2 ! 0tcp[13]表示 TCP 头第 14 个字节也就是标志位字节数值 2 代表 SYN 位。 2 ! 0表示“SYN 位被置 1”。这套语法虽然需要查表但在排查“连接建立失败”这类问题时非常精准。比如你想抓所有“发送 SYN 但没有任何响应的客户端”就可以用这个过滤把范围压缩到极小。3.3 三个实战场景SSH、HTTP、DNS只讲命令不讲场景很容易看完就忘。我来贴三个真实排查场景。场景一排查 SSH 登录失败想确认客户端到底有没有到服务器。tcpdump -i any -nn -c 50 tcp port 22 -w /tmp/ssh.pcap抓完把文件拷出来用 Wireshark 打开看是否存在连续重传的 SYN 包、是否为 RST 直接拒绝。如果客户端连着发 SYN 但服务器完全没有响应那大概率是防火墙拦截或服务没监听如果服务器回了 RST说明端口已经关闭或服务拒绝连接如果握手正常但认证失败那抓包已经帮不上忙了要去看日志和密钥。场景二定位一个 HTTP 接口为何偶发超时。tcpdump -i any -nn -s 0 tcp port 80 -w /tmp/http.pcap在 Wireshark 里打开后对出错的那一次请求 Follow TCP Stream。你会看到 HTTP 请求行、Header、Body接下来的关键参数是看客户端发出请求到收到响应的“时间差”到底消耗在哪个阶段。如果从 TCP 握手完成到发出 HTTP GET 有几百毫秒间隔那是客户端逻辑慢如果服务端收到请求后迟迟没有回包那是服务端处理慢如果服务端已经回包但客户端不 ACK、或出现重传那是网络传输问题。场景三DNS 解析缓慢。tcpdump -i any -nn -tttt udp port 53输出里能直接看到查询时间戳和响应时间戳。如果查询发出去到响应回来耗时超过几百毫秒多半是上游 DNS 服务器响应慢如果客户端反复重发查询说明中间有丢包。-tttt参数输出完整日期时间比默认的相对时间更容易判断耗时。4. Wireshark 分析把 pcap 变成线索4.1 打开文件与显示过滤器的正确姿势把 pcap 文件拷回本地用 WiresharkFile - Open打开。打开后建议立刻确认时间显示格式View - Time Display Format排查问题时我习惯设置成“Seconds Since Beginning of Capture”即包间相对时间这样能看到某个请求发生后隔多久出现响应如果是跨主机抓包对比则需要用 UTC 时间对齐。Wireshark 里也有一个“过滤器”但它叫显示过滤器只影响显示不影响原始数据。语法和 tcpdump 的捕获过滤器完全不同最典型的是相等运算符用字段名是点分结构http tcp.port 80 ip.addr 192.168.1.10 tcp.flags.syn 1 tcp.analysis.retransmissiontcp.analysis.retransmission是 Wireshark 分析引擎自动标记的重传包这个字段堪称排查丢包问题的神器。你可以在过滤器栏输入这个字段几万个包里所有重传瞬间全列出来配合tcp.analysis.duplicate_ack还能看快速重传和重复 ACK判断是否发生了网络拥塞或乱序。4.2 着色规则快速发现异常的视觉线索Wireshark 默认着色规则本身就是一套“诊断报告”浅蓝色是 DNS、绿色是 HTTP、黑色底白字是 TCP 问题包比如 RST、错误序号、红色是 TCP 重传、淡紫色是乱序包。一眼扫过去如果发现大面积的红色和黑色基本可以断定链路上丢包严重或服务端在主动断连。不过默认着色规则不是万能的在View - Coloring Rules里可以自定义。比如我想高亮所有访问某台数据库 IP 的包可以增加一条规则把匹配ip.addr 192.168.1.100的包设成黄色背景。在多场景混合抓包时这个技巧能极大节省肉眼寻找包的精力。4.3 Follow TCP Stream直接还原整次请求在包列表里右键任意一个 TCP 包选择Follow - TCP StreamWireshark 会把这个 TCP 流从建立到断开的所有 payload 按时间顺序重组。HTTP 调试时这就是一个完整的请求-响应记录不需要自己一条条翻 TCP 段。弹出窗口里还能分别查看“客户端发往服务端”和“服务端发往客户端”两个方向的数据排查响应内容异常时特别方便。对 HTTPS 流量默认 Follow 只能看到 TLS 密文。如果你只是想调试自己本地的服务可以通过设置环境变量SSLKEYLOGFILE让浏览器或 curl 导出 TLS 会话密钥然后在 Wireshark 的Preferences - Protocols - TLS里配置(Pre)-Master-Secret log filename选择刚才导出的密钥文件Wireshark 就能解密整个 TLS 会话明文 HTTP 内容都看得到。这个方法只适用于你完全可控的客户端和服务端用来调试自己的应用逻辑切勿用于任何未授权场景。4.4 tshark批量提取字段的自动化利器当 pcap 文件数量多起来用 GUI 一个个点就太慢了。tshark 可以做到“一条命令出结果”# 提取所有 HTTP 请求的源IP、域名和URI tshark -r /tmp/http.pcap -Y http.request -T fields -e ip.src -e http.host -e http.request.uri # 统计 TCP 连接对的数据量 tshark -r /tmp/http.pcap -q -z conv,tcp-Y后面的是显示过滤器-T fields -e指定要输出的字段字段名和 Wireshark 里的显示过滤字段完全一致。-z conv,tcp是统计 TCP 会话会输出一个包含成对地址、数据量、平均速率等信息的表格。只要把输出接到awk、sort、uniq等命令后面就能快速生成报告。比如分析半天抓包文件想知道流量都花在哪几个 IP 之间直接-z conv,tcp比肉眼可靠得多。5. 常见问题与排查技巧实录5.1 权限问题抓包报错 Operation not permitted装好 tcpdump 后普通用户执行抓包经常会遇到tcpdump: socket: Operation not permitted这是因为抓包套接字需要CAP_NET_RAW权限普通用户没有。常规解法是sudo tcpdump如果希望特定用户可以不用每次 sudo可以给 tcpdump 二进制加 capabilitiessudo setcap cap_net_raw,cap_net_admineip /usr/sbin/tcpdump这个命令让 tcpdump 在运行时只拥有网络抓包所需的最小权限而不是直接给用户 root 权限比chmod us更安全。Debian/Ubuntu 在安装 Wireshark 时默认配置了一个wireshark用户组把用户加进组里后使用 dumpcap 抓包也可以避免反复 sudo。5.2 抓不到想要的包先检查这三个原因抓包抓了个寂寞是最常见的求助贴素材。多数情况是以下三个原因网卡选错了。机器上有多块网卡流量走的不是你以为的那张。解决办法是先用tcpdump -i any抓一遍看看实际流量出现在哪个接口再精确定位。过滤表达式写错了。比如想看 HTTP 流量写成了host http这显然是无效表达式会被 tcpdump 直接报错忽略。更隐蔽的是写成httptcpdump 的捕获过滤器并不认这种高层的协议名需要写tcp port 80。要区分“捕获过滤器”和“显示过滤器”前者是 tcpdump 在抓包时用后者是 Wireshark 在分析时用两者语法完全不同。流量是加密的。抓到包但看不到明文不代表没抓到而是 TLS 层把 payload 封起来了。这时需要看的是 TLS ClientHello、ServerHello、证书等或者用 SSLKEYLOGFILE 解密权限范围内。5.3 大流量抓包时丢包怎么办在高吞吐链路上tcpdump 可能看到这样一行统计12 packets received by filter 0 packets dropped by kernel如果packets dropped by kernel不是 0说明内核 socket 缓冲区满了用户态程序来不及读取内核只能丢弃多余数据包。这会导致分析结果不准——你以为没有重传其实重传包还没到应用层就被丢了。解决办法从几个方向下手。先加大内核缓冲区# 把缓冲区调大到 2MB tcpdump -i eth0 -B 2048 -w /tmp/cap.pcap-B参数单位是 KB2048就是 2MB。其次写 pcap 文件尽量写到本地高速磁盘不要写到 NFS 网络盘不要再同时让包在屏幕上滚动打印直接用-w写文件省掉终端 I/O 开销。如果这样还丢包就考虑 dumpcap 接管它本身是专为高流量记录设计的并且支持多文件轮转能最大程度减少丢失。5.4 容器和虚拟化环境下抓包要注意命名空间在 Docker 容器里执行 tcpdump看到的网络命名空间是容器自己的通常只有 eth0 和 lo抓不到宿主机上其他容器的流量。想分析容器与外部通信的完整路径建议在宿主机上抓包。默认 docker0 网桥上会挂载所有容器的 veth 网卡用tcpdump -i docker0可以看到容器进出宿主机经过网桥的流量如果容器用了 host 网络模式那直接抓宿主机的物理网卡即可。还要注意在虚拟化环境VMware/KVM里宿主机抓包可能看到 guest 和外部通信的帧但每帧都会带着虚拟化网卡的 MAC和在 guest 内部看到的不完全一样。跨层排查时先明确抓包点否则容易对不上数据。5.5 时间不同步导致跨主机分析对不上当我们需要从客户端和服务端两个方向分别抓包合在一起分析时最怕两边时钟不一致。时间戳差个几秒握手包的先后顺序都会乱根本没法判断是“客户端先发”还是“服务端先回”。建议在抓包前用 NTP 或 chrony 同步客户端、服务端时钟然后在 Wireshark 里统一设置时间显示格式为 UTC或者使用相对时间减少人为误判。多机抓包时可以在每个抓包点手动记录一个基准时间比如同时执行date %s再把时间戳差减掉这个土办法在无法统一 NTP 的隔离网络里也曾救过我很多次。实测下来抓包最忌讳的是没想清楚就抓。我每次做抓包前都会先把问题写清楚要看哪个协议、什么端口、从哪台到哪台、持续多久。否则一抓几十万包全是噪音定位效率反而更低。对刚接触抓包的朋友建议先从回环接口 lo 开始开一个本机 nginx抓自己的 HTTP 访问把三次握手、HTTP 请求响应每一步都看明白再上真实环境。抓包是一种需要“手感”的调试能力多抓几次你也会慢慢形成自己的排查节奏。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价