OpenWrt 实时抓包:先定目标,再用 tcpdump 与 Wireshark 排障
网页打不开、某个设备连不上网、网速莫名变慢——这类问题靠猜测往往绕很多圈,直接看数据包是最短的路径:请求到底发出去没有、DNS 有没有回、TCP 握手卡在哪一步,包不会说谎。OpenWrt 上用 tcpdump 抓、电脑上用 Wireshark 看,是这套排查里最顺手的组合。
先把立场说在前面:抓包只应该用在你自己拥有或被明确授权管理的网络上,用来排查自己的故障。 抓包文件里可能含有账号、Cookie 等敏感内容,这一点在后面的隐私一节还会再强调。本文的流程按实际排障的顺序组织:先定目标,再决定在路由器本地存包还是实时送到电脑上看,最后才是过滤和分析。
第一步:先定清楚要抓什么
新手最常见的失败不是命令敲错,而是目标没定清就开抓,最后得到一个几百 MB 的文件,里面什么都有、什么都找不到。动手之前先回答三个问题。
第一,抓哪台设备的流量? 如果问题只出现在一台设备上(比如某台电视盒子连不上服务器),目标就是它的 IP 或 MAC,全程只围绕它抓。如果问题是全局性的(所有设备都慢),才需要看整体流量构成。
第二,在哪个接口上抓? 这是 OpenWrt 抓包最关键的选择,同一份流量在不同接口上看到的样子完全不同:
br-lan:LAN 侧桥接接口,看到的是内网设备的原始流量,源 IP 是内网地址。排查「某设备到底发了什么」在这里抓。- WAN 口接口(常见名为
eth0、eth1或pppoe-wan,以你的固件为准):看到的是经过 NAT 之后的流量,源地址已经变成公网 IP。排查「运营商那边到底通不通」在这里抓。 any:所有接口一起抓,信息量最大,也最容易把人淹没,只建议在定位「流量到底经过没经过这台路由器」时短时间使用。
还有一个必须提前知道的限制:流量不经过路由器,就抓不到。 同一个交换机或同一台路由器的两个 LAN 口设备之间互传文件,数据可能只在桥内转发,未必会出现在你的抓包点上;旁路由部署时也一样,只有一部分流量真正流经旁路由。发现「怎么抓都抓不到目标设备的包」时,先怀疑的是拓扑位置,而不是命令。
第三,抓哪个时间段、抓多少? 排障抓包讲究对准问题发生的瞬间:先想好复现动作(比如点开那个打不开的页面),抓包和复现同步进行,前后各留十几秒就够了。没有明确复现动作的间歇性问题,才考虑分段长时间抓,方法在下一节里。
抓包前检查清单
正式开抓前,逐项确认下面这份清单,能避开大多数第一次抓包会踩的坑:
- SSH 能以 root 登录路由器,密码或密钥可用(实时管道依赖这条通道)。
- tcpdump 已安装。OpenWrt 默认不带,用
opkg update && opkg install tcpdump安装完整版;存储实在紧张时用tcpdump-mini,核心抓包能力在,但个别功能被裁剪。装好后用tcpdump --version确认能运行,版本号以你固件里的为准,不必追求最新。 - 知道路由器的剩余内存。OpenWrt 的
/tmp是内存盘(tmpfs),抓包文件写多大就吃多少内存,文件失控会直接拖垮路由器。开抓前先用df -h /tmp和free心里有个底。 - 路由器时间是准的。系统时间没同步,抓包里的时间戳就是错的,后续和服务器日志、电脑上的记录对不上时间线。先确认 NTP 同步正常。
- 过滤条件已经想好草稿(第四节讲怎么写),停止条件也明确:抓够多少个包停(
-c)、单个文件多大滚动(-C)、多长时间一段(-G),三选一即可,不要裸奔开抓。 - 想好抓完的文件放哪、怎么取走、分析完是否删除。涉及他人设备的流量时,这一条尤其要提前想清楚。
第二步:在路由器上抓:本地存包
本地存包是最稳妥的模式:先把包存成 pcap 文件,再传到电脑上慢慢看。网络不稳定、问题出现时机不确定时,都优先用这种方式。
基本抓法
tcpdump -ni br-lan -s 0 -w /tmp/capture.pcap 'host 192.168.1.100'几个参数的取舍值得单独说,因为它们直接决定抓到的包有没有用:
-n:不做 DNS 反查,-i后面跟接口名。抓包时做地址解析既慢又会产生额外的 DNS 流量污染样本,养成永远带-n的习惯,需要更彻底时用-nn连端口名也不解析。-s 0:捕获每个包的完整内容。tcpdump 的默认截断长度在老版本上只有 68 或 96 字节,只够看包头,看不到载荷;新版本默认已经放大,但显式写-s 0不会有错。反过来,如果你只关心流量结构而不关心内容,把-s设成 96 能大幅减小文件体积,也天然少存敏感信息。-w:把原始包写入文件而不是打印成文本。排障分析几乎总是基于文件进行的,终端里滚屏看文本只适合快速确认「有没有流量」。
控制文件体积:数量、大小、时间三种封顶
# 只抓 1000 个包就自动停
tcpdump -ni br-lan -s 0 -c 1000 -w /tmp/capture.pcap
# 每个文件 10MB,滚动生成 capture.pcap0、capture.pcap1……
tcpdump -ni br-lan -s 0 -C 10 -w /tmp/capture.pcap
# 每 300 秒切一个新文件,文件名带时间戳
tcpdump -ni br-lan -s 0 -G 300 -w /tmp/capture_%Y%m%d_%H%M%S.pcap三种方式按需要选一种即可,也可以组合。配合 -C 时通常再加 -W 限制文件个数,防止滚动文件把 /tmp 慢慢填满。另外记得留意 tcpdump 结束时输出的统计:packets dropped by kernel 不为零,说明抓包期间路由器处理不过来丢过包,这份样本对「有没有丢包」类结论就不完整,分析时要把这一点算进去。高速网络下丢包明显,可以用 -B 适当调大内核缓冲区再试。
把文件取回电脑
scp root@192.168.1.1:/tmp/capture.pcap ./capture.pcapscp 最直接;用 LuCI 或 iStoreOS 的文件管理在网页上下载也可以,取的是同一个文件。取回之后及时删掉路由器上的副本,既腾内存,也减少敏感文件停留的时间。下载到电脑的 pcap 用 Wireshark 通过 File → Open 打开即可。
第三步:实时送到电脑上看:SSH 管道
问题能当场复现、想边操作边看包的时候,实时管道更直观:tcpdump 在路由器上抓,数据流经 SSH 直接喂给电脑上的 Wireshark,界面里即时滚动,不落文件。
原理一句话:tcpdump -w - 把 pcap 数据流写到标准输出,SSH 负责把这条流原样搬过网络,Wireshark 用 -i - 从标准输入读。
macOS / Linux
ssh root@192.168.1.1 "tcpdump -ni br-lan -s 0 -w - not port 22" | wireshark -k -i -前提是 wireshark 命令在 PATH 里。macOS 用 Homebrew 装的是图形应用,命令行启动方式以你本机实际为准,必要时用应用的完整路径。
Windows
Windows 上没有原生 ssh 管道给 Wireshark 的顺手方案,常用 PuTTY 套件里的 Plink 做 SSH 客户端:
plink.exe -batch -ssh -pw [密码] root@192.168.1.1 "tcpdump -ni br-lan -s 0 -w - not port 22" | "D:\Program Files\Wireshark\Wireshark.exe" -k -i -Plink 在 PuTTY 官方下载页面 获取,Wireshark 的路径按你的实际安装位置改。这条命令要在命令提示符(cmd)里执行,PowerShell 对这类二进制管道的处理方式不同,实测容易失败。另外两个 Windows 特有的坑:-batch 会禁止一切交互提问,所以第一次连接时主机密钥确认会被直接拒绝,先用 plink 单独连一次路由器、把密钥指纹确认并保存,之后再跑管道命令;把密码直接写在命令行里会留在命令历史和进程列表中,能用密钥登录就不要用 -pw 明文密码。
为什么过滤条件里必须排除 SSH 本身
注意两条命令里都有 not port 22。抓包流正通过 SSH 往外送,如果不排除 SSH 流量,抓到的 SSH 包会被再次封装进 SSH 流里送出去,形成正反馈:流量越抓越多,瞬间灌满。只要你是通过 SSH 远程抓包,这个排除条件就不能省;同理,如果你还开着其他会与路由器持续通信的管理通道,也可以一并排除掉。
实时管道的代价也要清楚:它占用的正是你要观察的网络本身,路由器性能弱、流量大时,管道本身会成为瓶颈甚至挤掉正常业务。抓不到关键瞬间的场合,老老实实回到本地存包模式。
第四步:过滤表达式怎么下手
过滤分两个阶段,很多人栽在把它们混为一谈上:
- 捕获过滤在抓包时生效,就是写给 tcpdump 的 BPF 表达式,一旦过滤掉就永久没了,抓完无法找回。
- 显示过滤在 Wireshark 里生效,语法完全不同(如
ip.addr == 192.168.1.100),只是在已有数据里筛选,随时可改。
所以策略是:捕获阶段只做粗筛(圈定设备和大致协议),宁可多抓一点;精细筛选留到 Wireshark 里做。下手顺序建议固定成一个套路:先用 host 圈住目标设备,确认能抓到它的包;再按问题类型叠加协议或端口条件;最后才做排除式的减法。
圈定对象:主机与网段
# 某台设备的全部流量
tcpdump -ni br-lan 'host 192.168.1.100'
# 只看它发出的(源)或发给它的(目的)
tcpdump -ni br-lan 'src host 192.168.1.100'
tcpdump -ni br-lan 'dst host 192.168.1.100'
# 整个网段
tcpdump -ni br-lan 'net 192.168.1.0/24'按协议与端口缩小
# DNS 查询与响应
tcpdump -ni br-lan 'udp port 53'
# Web 流量
tcpdump -ni br-lan 'tcp port 80 or tcp port 443'
# ICMP(ping)
tcpdump -ni br-lan 'icmp'
# 只看 TCP 握手发起(SYN 包),排查"连不上"时特别有用
tcpdump -ni br-lan 'tcp[tcpflags] & tcp-syn != 0'组合与排除
and、or、not 可以自由组合,复杂时用括号(在 shell 里记得给整个表达式加引号):
# 目标设备除 SSH 外的全部流量
tcpdump -ni br-lan 'host 192.168.1.100 and not port 22'
# 目标设备访问某台服务器的 HTTPS
tcpdump -ni br-lan 'src 192.168.1.100 and dst host 203.0.113.10 and tcp port 443'过滤写完先小规模试抓十几秒,确认抓到的正是想要的流量,再正式开始。直接上长时间抓包,错了就得整段重来。
第五步:拿到包之后,先看什么
面对一份几万个包的文件,不要从第一行开始逐包读。按下面的顺序切入,几分钟就能判断问题的大致方向。
先验证样本本身可信。 看总包数和时间跨度对不对,tcpdump 报告过 kernel 丢包没有,时间戳和问题发生时刻对不对得上。样本不可信,后面的分析都是白费。
再看全局构成。 Wireshark 的 Statistics → Protocol Hierarchy 看协议占比是否正常(比如 ARP 或某种广播异常地多),Statistics → Conversations 看谁在和谁说话、流量大头是谁。很多「网速慢」到这一步就已经定位到某台狂发流量的设备了。
然后追踪单个会话。 对可疑连接右键 Follow → TCP Stream,看这次会话的完整往返:请求发出了吗、对方回了什么、在哪一步断了。配合包列表里的标志位判断连接状态:只有 SYN 没有 SYN-ACK,是对方没回应或路上被拦;频繁出现 Retransmission,是链路在丢包;RST 则是某一端直接拒绝或中断了连接。
DNS 问题单独看。 显示过滤输入 dns,重点看有没有响应、响应码是什么(NXDomain 说明域名不存在或被拦截,ServFail 是解析服务出错),以及解析出的地址是不是你预期的那个。网页打不开的故障里有相当一部分止步于此。
显示过滤的常用式子先记这几个就够用:dns、http、ip.addr == 192.168.1.100、tcp.port == 443、tcp.analysis.retransmission(直接筛出重传包)。着色规则用默认的就行:标黑底红字的多是协议层面的异常包,值得优先点开。更系统的用法可以查 Wireshark 官方文档。
常见问题排查表
| 现象 | 先查什么 | 处理方向 |
|---|---|---|
| 一个包都抓不到 | 接口选对没、目标流量是否真经过这台路由器、过滤条件是否写错 | 先去掉过滤、用 any 接口短抓十秒验证链路,再逐项加回条件 |
| 只抓到广播和自己的包 | 目标设备流量是否只在交换机内部转发、是否旁路由只走了一部分流量 | 回到第一节的拓扑判断,换到流量真正经过的接口或设备上抓 |
| 抓到的包内容不完整、载荷被截断 | -s 参数 | 显式加 -s 0 抓完整包;只需包头分析时则有意用小值减体积 |
| tcpdump 报告 dropped by kernel | 路由器性能、写入速度、过滤是否太宽 | 收紧过滤、加 -B 调大缓冲、改本地存包、避开流量高峰 |
| 抓一会儿就报空间不足 | /tmp 是内存盘,文件是否设了封顶 | 加 -c/-C/-G 封顶,文件及时 scp 取走并删除,或挂载 USB 存储后改存外部设备 |
| Wireshark 管道启动了但没数据 | 是否在 cmd 而非 PowerShell 执行、Wireshark 路径、主机密钥是否已确认、SSH 本身能否登录 | 拆成两半验证:先单独 ssh 上去手动跑 tcpdump 看有没有输出,再接 Wireshark |
| 时间戳和实际对不上 | 路由器时钟与 NTP 同步状态 | 先同步时间再重抓,旧文件的时间线只能按偏移量人工校正 |
| 已建连接的流量只抓到开头几个包 | 固件是否开启了流量分载(flow offloading) | 分载会让已建立连接绕过抓包点,排障期间在防火墙设置里临时关闭软件/硬件分载再抓 |
性能与隐私:别长期全量抓
最后两件事,决定了抓包是排障工具还是新的麻烦来源。
性能上,抓包对小路由器不是免费的:每个经过的包都要复制一份送给 tcpdump,千兆流量全量抓取足以让低端设备的 CPU 吃满、转发延迟上升,甚至反过来制造丢包——你观察到的「故障」可能正是抓包本身造成的。所以原则是:过滤尽量前置、时长尽量短、问题复现完立刻停;需要长时间蹲守间歇性故障时,用分段滚动加数量封顶的小流量抓法,而不是无过滤全量抓。
隐私上,pcap 是原始流量的完整副本:未加密的账号密码、Cookie、聊天与浏览内容都可能原样躺在里面。规矩只有几条:只抓自己有权管理的网络;文件只存在自己的设备上,不随手发到公开渠道求助(真要请人看,先用只留包头的小 snaplen 样本或做地址匿名化);问题解决后及时删除路由器和电脑上的副本。另外提醒一次,路由器 /tmp 里的抓包文件在重启后会消失,别把它当成可靠的存档位置,重要的样本先取回电脑再说。
延伸阅读:抓包常和另外两类 OpenWrt 操作一起出现,可以配合看 DDNS 设置指南、IPv6 关闭教程 以及 iStoreOS 插件推荐。