写下 -o tun+ 看似精确,实际上是覆盖内核所有隧道的通配符。第二个 VPN 客户端、一个容器网桥,或者崩溃会话遗留的接口,都会满足它,主机于是放行了策略本想阻止的流量。下面的步骤固定一个设备名,按隧道能真正建立起来的顺序安排例外,并在规则落错时给你留一条退路。每一步都短到可以单独撤销。

第 1 步:记录现在的规则

改动默认策略之前先保存当前状态,让回滚成为一条命令而不是一段记忆。iptables-save > /root/iptables.pre 把每张表写入可恢复的文件;如果即将设置的策略切断了承载它的连接,另开一个持有 root 会话的终端算不上多疑。如果你在远程操作,还要安排一次 flush 作为保险开关。

然后列出接口,因为你想当然的名字,正是你本该读到的名字:ip -br link 显示当前存在什么,而隧道要等它起来才会出现。读的时候就把设备名记下来。

第 2 步:给隧道一个自己的名字

OpenVPN 在客户端配置中接受 dev tun_work,Linux 随后会创建一个正好用这个名字的接口,而不是分配 tun0。只要没有别的东西占用这个名字,它在重连之间保持稳定,这正是点名设备的规则有意义的原因。

名字无法控制时,改为匹配隧道地址或数据包标记。两种做法都有效,都更难读,而且隧道重新编号时都失败得更安静。无论如何,只匹配一样东西,并说清楚是哪一样。

第 3 步:先写 endpoint 例外,再写策略

仅 VPN 主机就是默认拒绝、外加一份短例外清单的主机,而最重要的例外是让隧道得以存在的那条。按这个顺序搭建,把 endpoint 规则放在隧道设备规则之前,握手才有地方可去:

# allow the tunnel to be built, then everything the tunnel carries
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -d 198.51.100.7 -p udp --dport 1194 -j ACCEPT
iptables -A OUTPUT -o tun_work -j ACCEPT
iptables -A INPUT  -i tun_work -j ACCEPT
iptables -A INPUT  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

endpoint 的字面地址和端口属于你的服务商,而不是本页。如果 endpoint 是主机名,解析一次并把结果固定下来,因为规则无法查名字,而轮换的答案会在下一次 DNS 变更后悄悄破坏策略。端口也要检查,因为把你迁到 TCP 443 的服务商否则就需要一条没人写下的规则。只在一个协议上能用的隧道,通常就是这处遗漏,而不是防火墙故障。

在路由器上,同样的形状进入 FORWARD 链,供其后的客户端使用,而路由器自身的流量需要自己的规则。只覆盖转发数据包的规则集,会把 SSH 和 DNS 留在旧路径上,路由器正是在隧道一起来的那一刻变得不可达。

第 4 步:检查顺序,而不只是存在

规则按顺序求值,所以更早出现的 ACCEPT 只是遮住了你后加的 REJECT。established 与 related 匹配,才让你自己出站请求的回包在没有打开通用入站路径的情况下返回;把它放在隧道放行之后,意味着隧道断开时返回流量仍走它自己的接口。

规则数量要少到一屏能读完。你无法审计的规则集,就是你会靠在顶部添加例外来打补丁的那种;默认拒绝策略正是这样一点点长出默认放行的边缘。改动前后各数一次 ACCEPT。

第 5 步:让它扛过启动和地址族

手敲的规则重启就没了,所以要从发行版的防火墙服务加载,或放在隧道接口存在之后才运行的 unit 里。在 OpenVPN 启动之前执行的脚本里引用 tun_work,是造成丢包启动循环的常见做法。

然后单独检查 IPv6,因为一份好的 IPv4 默认拒绝策略对另一个地址族什么也没说。ip -6 route 会告诉你主机是否有一条能绕过只处理 IPv4 的隧道的路由,而 ip6tables 或 nftables 需要自己的对等规则。用一个 IPv6-only 的目标去测,而不是相信规则集的对称性。

第 6 步:验证,并准备好恢复

把隧道启起来,确认你要的服务可用,然后试一件策略应当拒绝的事。如果答案出乎意料,用 iptables-restore < /root/iptables.pre 恢复,然后才动手改规则。持久化加上一条验证过的恢复路径,才让这件事成为你可以做第二次的变更。

相关文章