——使用 WireGuard 连通防火墙后的 IPv6 网络
背景:办公室如何访问校园网?
众所周知,网协办公室位于北理桥下,最近的校园网接入点是北食堂的 AP,网络波动巨大。前人留下的“流量卡 + CPE”方案满足了办公室的公网访问需求,但校园网资源依然无法访问。
解决方案有两种:
- 架设无线接收机,提高到北食堂 AP 的连接稳定性。
- 绕行公网,通过内网穿透等手段,连接办公室软路由和校园网——其实就是 VPN。
第二种看起来难度不高,且额外成本为零,值得一试。然而,最初的尝试很失败:校园网无法被主动访问,这符合预期;但办公室的网络,无论是 IPv4 打洞还是 IPv6,也都无法被主动访问。
排查的结果指向 CPE 防火墙。然而,CPE 的管理页面和没有差不多,网上也难以找到对应的破解资料。看来这一方案失败了……吗?
原理:有状态防火墙如何放行回包?
不妨回过头来,思考一下防火墙的特点:它会阻断外部主动发起的连接,但内部向外的访问不受影响,否则 IPv6 就无法正常使用了。那它是如何实现这一功能的呢?
此处需要注意一个常见的误区:很多人会认为连接发起者是主动的,响应者则是被动的。从请求的角度,确实如此;但对于底层的网络包,上下行其实都是一方“主动”发送的。
也就是说,防火墙如果只看包的来源和去向,并不能确定某个请求是外部主动发起的,还是内部请求收到的回复。因此,防火墙会在内部发起请求时,记录请求来源和目标,并临时放行来自该目标的返回流量。这就是有状态防火墙,也是 UDP 打洞能够成立的基础。
有时防火墙很宽松,允许任意来源的流量从这扇临时门进入;但更多时候,防火墙只允许来自记录的目标的流量进入。这种情况下,仅仅向 STUN 服务器发包,并不能得到一个任意公网设备都能访问的入口。
然而,我们真的需要让任意公网设备都能主动访问本地吗?我们的需求,只是让校园网内的一台固定设备与办公室互通。既然通信对端已知,为什么不直接向它发包呢?
因此,只需要在发送内部请求时,将目标定为需要连接的端点,防火墙就会放行对端发“回”的流量;而对端也如此操作,便可建立双向连接,成功“打洞”!
思考:这真的算打洞吗?
对于 A 侧防火墙,A 正常向外部的 B 发送请求,防火墙的预期是收到 B 的回包。只是因为 B 侧也有防火墙,所以 B 并未真的收到 A 的包,无法发回响应。
但是,谁说 B 一定要先收到包才能回复?我们直接让 B 向 A 发请求,此时对 A 侧防火墙来说,不就像是 B 收到并响应了 A 的请求吗?反过来也如此。也就是说,对于两端防火墙,这些包都符合正常的放行规则。
类比一下,就像是有两个人,家门口都装了只能从内部打开的门。如果只有一方去找另一方,就会被对方的门拦在外面;但如果两方都主动去找对方,就会同时打开两家的门,道路畅通无阻。
使用 WireGuard 建立连接
弄清原理,剩下的就是找一个能让两端持续互发 UDP、同时承载校园网流量的工具。WireGuard 恰好就能完成这件事。
不过,和一般的 WireGuard 配置不同,这里需要:
- 两端都配置对端 IP,即
Endpoint。 - 两端都固定发送和监听端口。
- 两端都设置
PersistentKeepalive时间,进行保活。
校园网内设备的配置如下:
[Interface]Address = 192.168.63.2/24ListenPort = 42371PrivateKey =
[Peer]PublicKey =Endpoint = [2409:8900...]:42371AllowedIPs = 192.168.63.1/32PersistentKeepalive = 25这里的 PrivateKey、PublicKey 需要填写对应密钥,Endpoint 中省略的 IPv6 地址需要替换为办公室端的完整地址。
OpenWrt 后续配置
确认 WireGuard 握手成功后,就是一些基础配置了。
路由与防火墙
在办公室软路由上完成以下设置:
- 在 WireGuard 对端的“允许的 IP”中添加
10.0.0.0/8。 - 勾选“路由允许的 IP”,以自动将指向校园网 IP 的请求路由到 WireGuard。
- 新建
wg防火墙区域,添加lan → wg转发规则。
DNS 解析
另外,还有个小坑:OpenWrt 默认启用的 DNS 重绑定保护会拦截上游 DNS 返回的私网地址。除了关闭这一功能,也可以把需要访问的校园网域名加入重绑定保护白名单,允许这些域名返回私网地址。