隧道建起来了,客户端也认证成功,但网关后面的 LAN 依然看不见。本该解决这个问题的规则放行了 VPN 端口,而且完全按写的那样工作,因为它管的是发往网关本身的报文。客户端发往网关后面某台主机的流量,目的地址不同,走的链也不同。登录成功并不改变内核去查这两条链中的哪一条。

两条链,两个不同的目的

报文的命运由它去哪里决定,而不是由它怎么来决定。发往网关地址的流量在本地交付,并按入站规则评估。网关要往前转发的流量,按转发规则评估。同一个隧道接口可以产生这两类报文,所以一条规则覆盖不了两件事。

整个误解就一句话:放行监听端口,跟放行它后面的网络毫无关系。这是两个各自独立的判断,各自需要证据;两边都写着同一个接口名,也不会把它们合并。

监听规则实际放行的是什么

监听端口的报文终止在 VPN 进程里,这才使隧道能够建立。网关上管理页面的访问和本地诊断的应答也走主机自己的入站路径,所以对网关做的测试能通过,而它后面的一切都失败。两个结果都没错,也都跟 LAN 无关。

当进程把客户端发往别处的流量解封装之后,报文进入转发路径,那里才需要授权。认证成功只决定了客户端是谁,并没有决定它能去哪里。两个问题各有各的负责人、日志和报错。

从客户端测,永远不要从网关测

在网关上生成的测试走的是主机自己的出站路径,即使转发路径关着也可能通过。测试要从客户端发起,并且同时观察流的两端。

nc -vz 10.40.7.25 445
tcpdump -ni tun0 host 10.40.7.25

如果请求出现在 tun0 上、而目的地什么也没收到,说明报文到达后被丢弃了,问题在转发规则或目的地自己的过滤上。如果 tun0 上什么都没有,客户端根本没把它送进隧道,问题在客户端的路由,而不是网关的策略。再对比那种正确发出却什么也没回来的请求,那就是回程路径的问题。

转发需要三样东西,不是一样

内核转发要打开,过滤规则要放行这条流,目的地要可达并且回程有路可走。三样缺一样,从客户端看都是同样的沉默。

sysctl net.ipv4.ip_forward
sudo iptables -S FORWARD
sudo iptables -S INPUT

把三条输出放在一起读。第一条是零,后面两条就没有意义;第二条是默认丢弃,客户端的报文被丢掉,而网关自己的流量照常工作。第三条输出说明了为什么监听规则从来就不是问题。

在文档里把两套规则分开写

监听规则和转发服务的规则要写成两行,各有各的负责人和理由。VPN 端口变了,或者发布了新服务,这种分离能防止一处改动悄悄扩大了另一处。

与其把每个通过认证的对端都当成可信的 LAN 成员,不如只对真正需要的客户端网段和服务使用范围很窄的规则。StrongSwan 的转发说明讲的是同一条边界上回程路由和地址转换的那一侧,这又是第三个判断。

最后,用户被拒绝的时候要把层次分清。请求到了主机、应用拒绝了账号,就该在这一层修应用的权限;放宽转发既变不出文件共享的凭据,还会把所有能连上的人的权限一起放大。

相关文章