为锁紧 WireGuard 而封禁 IPv6 会弄坏主机
丢弃全部 IPv6 的输入规则同时会移除邻居发现和 Packet Too Big。把三项职责分开,再确认主机依然可用。
目标本身是合理的:只应让隧道用户访问这台机器上的服务。人们常用的做法是一条 IPv6 输入链,除 WireGuard 之外全部丢弃,而这同时丢掉了让主机留在自己链路之上的流量。邻居发现和路径维护报文并不属于服务访问,把它们删掉会造出一台因与你的策略无关的原因而不可达的机器。隧道起来了,服务范围也划对了,链路上其他一切都不工作。
三项职责,一套规则
第一项职责是外层网络运行:主机必须留在自己的链路上、解析邻居,并了解该链路的路径上限。第二项是加密监听,在你选定的地址和端口上接收 UDP。第三项是你希望隧道用户访问的那组解密后服务。
这是三套不同的策略,只有第二和第三与 VPN 有关。把它们当成一套的规则集会继承一种失效方式:收紧应用边界时,主机的链路附着被悄悄弄坏。
把它们放在不同的链里,至少用不同的注释隔开,好让下一个人看清哪一行是为了什么存在。
ICMPv6 为主机做了什么
IPv6 依赖 ICMPv6 的地方远不止回显。邻居请求与通告取代 ARP,是本地交付所必需的。Packet Too Big 携带路径 MTU 信息,忽略它会让大包传输卡住。链路使用自动配置时,路由器通告携带默认路由和前缀信息。
RFC 4890 把主机过滤器必须放行的报文与属于管理选择的报文分开,而且是在与转发路由器规则不同的主机一节里讲的。只读转发那一节,得到的输入策略对被保护的主机来说过严。
实用规则是:在需要它的接口上放行必要的差错与配置报文,在平台允许的地方按类型和来源限定范围,对其余部分作出明确决定。
把这些统统换成 ICMPv6 全放行,可用性问题解决了,过滤却没了。换成统统丢弃,过滤问题解决了,主机却没了。
先放行隧道,再放行服务
在预定的外层地址和 UDP 端口上接受 WireGuard 传输,并通过连接跟踪接受回程流量。然后允许应用服务经由隧道接口通过,来源只限于你真正授权的那些。
对外层 UDP 端口的放行,并不等于授权其中的解密请求。正是这个区分,构成了隧道接口必须出现在服务规则里的全部理由。
sudo nft list ruleset
ip -6 addr show
ip -6 route show default
物理地址上的监听,与隧道地址上的同一服务是两处不同的暴露。如果这台机器还向另一台转发流量,那属于转发链的决定,不是这条输入策略,需要单独论证。
要测链路,不能只测隧道
改动后隧道能用,证明的东西比看上去少:既有的邻居表项和已建立的连接,会掩盖策略如今丢弃的某条控制报文。
直接检查附着情况,再检查被排除的路径是否仍然失败:
ip -6 neigh show
ping -6 -c 3 2001:db8:1::1
sudo nft -c -f /etc/nftables.conf
重启后邻居表仍然完整,说明发现机制还在工作;表被清空且再也填不满,说明你把它过滤掉了。第三条命令在不应用的前提下校验规则集语法,趁着还有会话时值得做。
把自己关在外面之后,如何救回主机
改动承载你自己管理会话的防火墙规则之前,先留第二条通道:控制台、串口连接,或者一条定时回滚——你不取消它,它就把新规则撤掉。
万一改动真把你关在外面,恢复要走那条通道,而不是走你刚删掉的网络。从保存的副本恢复上一套规则,确认主机重新可达,然后再把预定策略拆成小块逐段应用。
最终策略并不通用。地址规划、路由和防火墙实现都是部署输入,但边界处处相同:拒绝非预期的应用访问,同时保留承载已授权隧道的控制流量。