VPN 已连接但防火墙仍在拦截:如何判断问题出在哪一层
隧道已经建立,却仍有一个端口不通。先读路径,再读每一层的策略,改动最窄的那条规则,而不是关掉两个控制中的任何一个。
客户端说已连接,资源仍然拒绝,而惯常的下一步是把某个东西关掉。这句话里的两个控制做的是不同的事:VPN 为被覆盖的流量铺一条路径,防火墙则逐连接决定流量能否通过。一条能用的隧道配上拒绝的策略,从使用者的座位上看起来和坏掉的隧道一模一样,所以任务就是弄清是哪一层在回答。以下是我采用的顺序,以及每种读法对应的停止信号。
把路径和策略分开
从故障的形态入手,因为这是免费的信息。丢包会造成超时:客户端重试,什么也不回来,命令一直挂到放弃为止。拒绝会给出拒绝或重置:有东西回应了,并说了不。服务根本没在监听时,是主机自己拒绝,完全不涉及防火墙。
这三种结果指向不同的层。超时意味着某处的策略在静默丢弃,或者路径根本没离开这台机器。拒绝意味着你到达了主机,而它的协议栈或主机防火墙说了不。彻底没有回应,隧道接口却是通的、也没有到目的地的路由,意味着路径错了,任何防火墙规则都修不好。
一次读完路径
在看第一条规则之前,先确认隧道覆盖了目的地。只承载办公网段的分流隧道不会把请求送到另一个网段,那时故障看起来像防火墙拦截,其实不是:
ip route get 10.20.4.15
ip -brief address show
wg show
sudo ipsec statusall
路由的输出会指出报文从哪个接口离开、携带哪个源地址。如果那个接口是你的物理网卡而不是隧道,问题就在路由或隧道的允许网段上,属于 VPN 配置而不属于防火墙。
有一个 VPN 特有的坑值得单独检查。在 WireGuard 里,对端的 AllowedIPs 既是路由也是密码学过滤器:源地址不在对端允许集合里的报文,在任何防火墙规则被查询之前就会被丢弃。所以一个完全正确的主机防火墙,可能站在一次看起来像策略的静默丢弃后面,而修法是密钥配置里的一行,不是一条规则。
在真正回答的那一层读策略
路径正确之后,从主机往外走一遍策略,盯住计数器在动的那一层:
ss -ltn | grep ':443'
sudo nft list ruleset
sudo iptables -S INPUT
sudo ufw status verbose
监听中的套接字回答的是另一个问题。端口上没有任何监听时,内核会拒绝连接,任何入站规则都不相关。套接字存在、而来自远端客户端的连接超时,说明路径上某处在丢弃,规则的计数器会告诉你是不是丢在这里。
与其从外面猜,不如给你怀疑的配置文件或链打开日志。一条记录了源、目的和端口的丢弃,就能定位到层和规则,它也证明了报文确实到达过,这是客户端侧的任何测试都无法确立的。
隧道在那里终止时,读网关的决定
在站点到站点或远程访问网关上,VPN 认证用户,策略授权资源,这是两份独立的授权。被允许进入隧道的人,并不会自动被允许访问每一台内网主机,拒绝往往来自一条转发规则,而隧道本身是健康的。同样的分离也出现在 IPsec 里:挑选流量的安全策略与放行它的过滤器是两回事,所以两者在 RFC 4301。
回程路径要和去程一样仔细检查。 有状态过滤需要看到回复,所以经隧道去、绕隧道回的这条不对称路径,会产生看起来随机、并且只从部分客户端复现的丢弃。如果流量到达网关就停下,先把转发规则和回程路由放在一起读,再考虑放宽任何东西。
网关也是 NAT 或伪装规则能藏住真实源的地方。如果内网主机看到的是网关地址而不是客户端,它们那些本该匹配客户端地址池的主机防火墙规则就永远不会命中,而修法在网关上,不在每台服务器上。
改动最窄的一层,然后验证
不要做宽泛的修复。关掉主机防火墙、加一条放行一切的规则,或者把每个接口都划进受信任配置文件,这些做法各自都拆掉了正在干活的控制,而改动会在事故之后继续存在。一条只限定源网段和那个端口的规则更容易复核、更容易撤销,也让机器上其余的规则原样保留。
用当初失败的那个测试,从同一台客户端验证,然后在重连之后再验一次,因为一条在隧道重新协商之前匹配的规则,之后可能就不再匹配:
nc -vz 10.20.4.15 443
curl -v --max-time 5 https://10.20.4.15/
在收尾之前:
- 到目的地的路径从隧道接口出去,源地址与策略的预期一致。
- 端口上确实有东西在监听,拒绝或超时被归到某条具名规则上,而不是被假定。
- 网关在两个方向都转发,目的地看到的是你写规则时针对的那个源。
- 没有为了通过测试而关掉任何控制,你做的改动只点名一个源网段和一个端口。