在 VPN 主机上抓包,记录下来的并不是同一件东西。内核会把数据包暴露两次:一次是包好的,在物理网卡上;一次是拆开的,在隧道设备上。选哪块网卡,就等于选你读的是哪个故事。大多数关于抓包能证明什么的争论,其实是关于采集了哪个故事的争论。

封装造出两种视角

隧道把应用产生的数据包拿过来,塞进一个目的地是 VPN 服务器的新包里。内层形态出现在 tun0、wg0 或客户端创建的任何设备上。外层形态出现在把它送往网络的那块网卡上。两种形态都合法,它们回答的是不同问题。要分别采集,因为两者头部不同、读者也不同。

sudo tcpdump -i tun0 -n -s 0
sudo tcpdump -i eth0 -n host 198.51.100.20 and udp port 51820

做这个对比,伪接口 any 是个糟糕的选择。被转发的包可能被记录两次,本机生成的包又会以两种形态出现,把计数撑大。如果数字看着不可能,先检查网卡,再怪隧道。

隧道里面,数据包很普通

在隧道设备上,你看到的就是应用让内核发出去的东西。目的地址、端口、DNS 名、TLS 服务器名、大小和时间全都在。TLS 载荷仍由应用自己的会话加密,所以抓包看不到页面内容。明文 DNS 查询在这里可见,尽管它的载体是加密的,因为它从来就没被保护过。

加密 DNS 会去掉那唯一一个可见字段。它藏不住目的地址、字节数或节奏,这些是流的属性,不是查询的属性。

外面只剩封装和它的形状

物理网卡显示你的地址、服务器地址、端口、包大小和时间。里面承载的目的地不在其中,但它们的形状仍可能支持推断。大小和节奏可以暗示视频流、批量传输或聊天会话,却不必点出其中任何一个。附近的观察者看到的景象大致相同,这也解释了隧道为何能一边隐藏站点,一边暴露自己的存在。

这个说法取决于路由。更窄的路由、不进入隧道的 IPv6 默认路由,或绑定物理网卡的进程,都会把流量放到封装之外。下结论之前,先读实际路由。

对端地址与抓包卫生

TCP 模式的 OpenVPN 保持一个已建立的套接字,所以套接字表能指出对端。UDP 模式的 OpenVPN 常让套接字处于未连接状态,ss 可能只显示本地一侧。这时应改读配置里的 remote、详细的客户端日志,或到端点的路由。WireGuard 会直接报告端点和最近一次握手。

wg show
ss -tunp | grep 51820

抓包文件比产生它的会话活得更久。它会被复制,也可能被任何有本地访问权的人读到。只留调查需要的内容,限制权限,工作结束就删掉。

可分享的抓包应当说明是哪块网卡、什么时候抓的。没有这条注记,下一位读者只能猜自己在看哪一层。

相关文章