linux需setcap cap_net_raw+ep,macos须过滤无效接口,windows需装npcap并启用兼容模式;pcapng须转libpcap格式;http解析需关键词匹配或tcpassembly流重组;linktype必须动态获取而非硬编码。

pcap.OpenLive 权限拒绝不是代码写错了
Linux/macOS 下 pcap.OpenLive 直接 panic 或返回 permission denied,99% 是权限问题,不是你漏写了参数或设备名拼错。
Linux 必须显式赋予二进制文件 cap_net_raw 能力,而不是每次 sudo ./your-binary——后者放大攻击面且无法在 systemd 服务里复用:
- 运行
sudo setcap cap_net_raw+ep ./your-binary,之后普通用户可直接执行 - 验证:
getcap ./your-binary应输出./your-binary = cap_net_raw+ep - macOS 上 SIP 可能屏蔽部分接口,
en0不是万能解;必须先调pcap.FindAllDevs(),过滤掉Addresses全是127.0.0.1或::1的设备再选 - Windows 静默失败大概率因没装 Npcap(WinPcap 已停更),安装时务必勾选 “WinPcap compatibility mode”
pcapng 文件一打开就静默失败
gopacket 原生不支持 pcapng 格式,Wireshark 默认导出就是 pcapng,但 pcap.OpenOffline 不会报错,而是 packetSource.Next() 立即返回 nil,接着调 packet.Layer() 就 panic。
确认方式很简单:
- 终端执行
file your.pcap,输出含tcpdump或libpcap→ 可用;含pcap-ng→ 不可用 - Wireshark 正确导出路径:File → Export Packet Dissections → As PCAP (libpcap)
- 已有 pcapng?用
tshark -F libpcap -r input.pcapng -w output.pcap转换,tshark自身支持 pcapng
packet.Layer(layers.LayerTypeHTTP) 总是 nil
这不是 HTTP 包没抓到,是 gopacket 默认不重组 TCP 流、不处理 TLS、不识别 chunked 编码,layers.LayerTypeHTTP 只对“单个 TCP 包里恰好含完整 HTTP 报文头”有效——现实中几乎不存在这种包。
别在循环里对每个 tcp.Payload() 直接调 http.ReadRequest,它需要完整未分片流,而 pcap 抓的是帧。
简单可靠方案:
- 用
bytes.Contains(tcpLayer.Payload(), []byte("GET "))做关键词匹配(注意空格和大小写) - 真要还原完整请求/响应:必须上
gopacket/tcpassembly,自己维护streamFactory和连接超时清理逻辑,否则内存持续增长 - Wireshark 能显示 HTTP 是因为它后台做了流重组 + 解密 + 解压缩;
gopacket只解帧、IP、TCP,到此为止
LinkType 写死导致所有上层解析失败
硬编码 layers.LinkTypeEthernet 等于放弃解码。真实链路层类型取决于平台和抓包方式:
- Linux
any接口 →LinkTypeLinuxSLL(值 113) - 环回接口(
lo)→LinkTypeNull(值 0) - VLAN 或 PPP 接口 → 各自对应不同类型
- 必须从
handle.LinkType()动态获取,不能写死字符串或数值
packet.NetworkLayer() 就是 nil,后续所有 IP/TCP 层解析都失效,但 packet.Data() 还在——字节没丢,只是解不出来结构。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











