UFW 的断网开关挡住了你的 VPN?放行对端
你的拒绝出站规则把隧道握手丢掉了。在 ufw enable 之前添加的一条对端例外,正是把这条策略变成断网开关的东西。
你照着清单做了:拒绝出站、放行隧道、启用 ufw。结果客户端卡在握手、始终连不上,或者连上了却打不开任何页面。两种失败出自同一个缺口:让隧道得以存在的那条规则缺失了,因为隧道并不是你的数据包真正离开的接口。
为什么针对 tun0 的放行一开始什么都匹配不到
tun0 要等会话建立之后才由客户端创建。建立这个会话的数据报是发往服务商 1194 端口的普通 UDP 包,它们带着物理源地址从 wlan0 或 eth0 出去。allow out on tun0 只匹配出接口为 tun0 的流量,所以在握手期间它什么都匹配不到。
再叠加default deny outgoing,外层数据包在接口出现之前就被丢弃了。客户端不断重试、超时,然后报 TLS 或握手失败,于是人们转去翻证书、调 MTU,而防火墙正悄悄吞掉连接。本用来圈住流量的规则,反而让这股流量无法被圈住。
本能式的修法会让泄漏变成永久。sudo ufw allow out on wlan0,或者把默认策略改回放行,隧道是起来了,机器却不再有断网开关:下次隧道一掉,所有流量立刻改走物理网卡。我整整丢了一个下午,才弄明白自己到底在过滤哪个包。
两组数据包各自需要什么
你的流量会两次穿过防火墙,以两种形态出现。内层数据包从隧道地址经 tun0 出去;外层数据包从物理地址发往对端,而它是线路上唯一可见的东西。每种形态各配一条规则:
sudo ufw allow out on tun0
sudo ufw allow out to 203.0.113.10 port 1194 proto udp
sudo ufw allow out to 203.0.113.10 port 443 proto tcp comment 'tcp fallback'
把地址和端口换成你自己配置文件里的值。WireGuard 对端通常应答 51820/udp;走 TCP 443 的 OpenVPN 配置则要换成那个端口。细节不同,形态不变:两条规则都很窄,合起来划定了隧道断开时机器唯一能到达的目的地。
顺序是第二个误区。用原生 iptables 时,你会从上到下读链,再推理哪条规则生效。ufw 不是你输入列表的薄包装,它会把规则编译进自己的链,并自行选择插入点。ufw status 按 ufw 的顺序打印,而不是你的顺序。当某条规则看起来没生效时,先在改写任何东西之前,把ufw show added 和iptables -S | grep ufw 里编译出的规则集做对比。
例外必须始终只有一个地址宽
对端规则只在它写明的地址正是客户端拨号地址时才成立。服务商会轮换接入点,而解析主机名的配置会随 DNS 变更换到新地址,规则却还指着旧地址。一条用了几个月的隧道突然起不来时,先拿规则里的地址和客户端正在请求的地址对照,再决定要不要放宽。
放宽到整个子网,或放宽到 1194 端口的任何目的地址,就把策略又变回一个有洞的防火墙。例外才是断网开关;一旦放宽,就没有东西可断了。把它固定在一个地址上,并留下一句注释说明它属于哪个配置、哪个服务商,因为半年后这个地址会显得莫名其妙。
域名解析值得单独一行。查询发生在隧道存在之前,走的是物理接口,所以严格的拒绝出站策略可能让客户端连自己的服务器都找不到。要么对解析器地址放行 53 端口,要么先解析一次并把地址钉死在配置里。在所有接口上都放行 DNS 是一个决定,而不是默认值。
在需要隧道之前先把策略建好
ufw enable 会一次性应用整套策略并重载它的链,而在运行中的防火墙上改动默认策略同样会重载。ufw 手册 警告这会切断包括 SSH 在内的现有连接。所以命令要按这个顺序来:SSH 规则放在启用之前,并保持一个控制台会话开着:
sudo ufw default deny incoming
sudo ufw default deny outgoing
sudo ufw allow out on tun0
sudo ufw allow out to 203.0.113.10 port 1194 proto udp
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verbose
ufw reset 是故意不放进那段脚本的。它会删除所有规则并停用防火墙,而在远程主机上,紧接着的启用正是掐断你会话的那一步。如果确实要重置,先补上 SSH 规则,并在继续之前用控制台确认第二条回程。
顺序不是装饰。ufw 运行期间添加的规则不会清空任何东西,但你翻转默认策略的那一刻,链会被重载,旧策略允许的会话也随之消失。把默认值、放行规则和启用动作放在一次完成,趁你还有一条不依赖这台机器的进入路径。
测试被切断的状态,并保留撤销手段
没测过的断网开关只是猜测。故意断开客户端再试着打开页面:必须失败。重新连接后,它必须在不碰任何规则的情况下恢复。sudo ufw status verbose 用来确认默认值和日志状态,而ufw status numbered 会告诉你在测试规则完成使命后该删掉哪一条。
把反向脚本放在正向脚本旁边。一台拒绝出站、隧道又挂掉的机器没法自己下载修复脚本,所以撤销手段必须躺在磁盘上,并且能从控制台读到:
sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
在隧道已经断开、必须撤掉规则的时候运行它,而不是把它当日常步骤。关掉终端之前,四件事应当成立:对端规则只写一个地址,DNS 有明确的例外,启用发生在放行之后,拔掉隧道会切断普通流量而不会把客户端彻底弄死。