VPN 客户端连上了却没有网络:缺失的三个环节
能回应 ping 的隧道仍然需要转发、地址转换和一条转发规则。再次修改客户端之前,先弄清楚三者中缺的是哪一个。
客户端拿到了地址,服务器也能回应 ping,可每个页面依旧超时。多数人这时开始改客户端配置,而这份功夫通常是白费的:隧道一旦建立,服务器就必须像路由器一样工作。三个条件必须同时成立,数据包才能出去、回应才能回来;无论缺哪一个,症状都一模一样。
为什么隧道通了却仍然没有出口
内核必须在接口之间转发数据包,而多数 Linux 发行版默认关闭这一功能。流量必须转换成外部世界能够回应的地址,除非每一级上游路由器都已知道通往隧道网段的回程路由。防火墙的转发链必须放行两个方向的流量,包括回应包。
这三件事都可以单独修好,陷阱也正在这里。只开转发而不加地址转换,数据包会带着私有源地址出去,却没有回程。只加地址转换而不开转发,内核会在下一步把包丢掉。
所以应当逐层检查,而不是盯着客户端;一次只改一处,结果才有意义。
转发是必须持久化的内核开关
改动之前先看当前值,改完再确认设置确实生效。
sysctl net.ipv4.ip_forward
sysctl -w net.ipv4.ip_forward=1
sysctl net.ipv4.ip_forward第一条命令报告当前值,第二条在运行时打开,第三条证明写入确实生效。运行时值会在下次重启后消失,这正是维护之后配置没动、连接却坏掉的原因。
把它写进 /etc/sysctl.d/ 下的文件以持久化,然后直接应用该文件,而不是靠重启来验证。FreeBSD 上对应的是 net.inet.ip.forwarding,要持久化则需在 rc.conf 中写入 gateway_enable=YES。一台报告转发已关闭的设备,可以解释一整类「包能进来、却什么都不回」的故障。每次升级后也要复查这项设置,因为重新编译的内核或更换的设备镜像可能悄悄把它改回去。
选择 masquerade 或一个固定转换地址
外部地址是动态的时候,masquerade 是最简单也最正确的形式。把隧道网段当作源、把外网接口当作出口。
iptables -t nat -A POSTROUTING -s 10.9.0.0/24 -o eth0 -j MASQUERADE外部地址是静态公网地址时,把源地址转换成那个确切地址更可预测,也更容易审计。
iptables -t nat -A POSTROUTING -s 10.9.0.0/24 -j SNAT --to-source 198.51.100.10第二种形式带着维护陷阱:写死的地址一旦变化,隧道照旧可用,上网却会悄悄中断。要么使用 masquerade,要么在运营商迁移时同步更新规则。接口选择同样重要,因为共享自身上游隧道的路由器必须经那条隧道转换出去,而不是走物理 WAN。
filter 表是第三道门
转发和地址转换都正确,数据包仍可能死在 filter 表里。ufw 是常见元凶:它的转发策略出厂即为 DROP,其余配置看起来完全正确,这一个设置却把流量掐死。把它抬起来是有意的安全决策,不是勾选框。
iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT第一条规则放行从隧道去往外面的新连接,第二条只放行回来的回应。两条都应收窄到隧道网段和预期目标,因为对隧道接口一概放行,等于把 VPN 变成谁通过认证都能用的开放出口。
桥接的隧道需要另一种答案。地址属于网桥而不是物理端口,所以把接口从属给网桥会移除它原有的地址,主机看上去不可达,直到网桥自己拿到地址——这可以由 dhclient br0 完成。这个故障看起来像 VPN 问题,实际上是二层问题。动防火墙之前先检查网桥自己的地址,因为改 filter 修不好一台已经没有地址可用的主机。
页面始终打不开时该看哪里
先 ping 服务器的隧道地址,确认隧道存在。再从客户端向公网地址跑一次 traceroute,看它停在哪里:停在服务器,说明包到了却没有被转发或转换;越过服务器之后才停,问题在上游,不在你手里。
ping -c 3 10.9.0.1
traceroute -n 198.51.100.10第一条命令证明隧道能把流量送到服务器本身,第二条显示数据包向外能走多远。追踪停在隧道地址,指向服务器上的转发或地址转换;追踪在下一跳才停,指向运营商或上游路由器的回程。
在服务器上盯着外网接口,让客户端加载页面。出方向带着私有源地址,说明缺地址转换;完全没有回应,说明包被转发链或上游回程丢掉了。
如果远端客户端还要访问服务器局域网内的主机,别忘了局域网也需要一条回隧道网段的路由。这属于路由而不是地址转换,也是上网通了之后最常被忽略的一步。