两台笔记本电脑接在同一个家庭网络上,而公司 VPN 只接受其中一台。第二台要么超时,要么一直等到第一台断开,而且两次尝试之间没有人改动过客户端设置。凭据还是一分钟前能用的那一套,这正是认证并非故障原因的线索。有三种机制会造成这种局面,而服务器自己的日志会告诉你是哪一种。

先读网关日志,再动客户端

服务器对两次尝试的记录能回答第一个问题,答案只有三种。如果第二次尝试从未出现在日志里,说明数据包根本没到监听端,问题出在家里的路由器或运营商的线路上。如果日志记录了这次尝试并拒绝了它,说明隧道已经到了,问题在身份、授权或会话上限,而不在线路上。如果日志记录了成功的会话,客户端却仍然报错,就去看回程路径,或者看是不是两台客户端拿到了同一个隧道地址。

手机热点能廉价地把这两类原因分开:在第一台保持连接的同时,用移动数据跑第二台客户端。那边成功就指向家庭网络,那边同样失败就指向网关,路由器因此可以排除。两个结果单看都不算定论,但每一次都能用一次尝试砍掉一半排查范围。

动手之前先把结果写下来,因为日志的三种结局对应三种互不相干的修法。写明你看到的是哪一种,比一张客户端报错截图有价值得多。

路由器对 GRE 和 NAT-T 做了什么

PPTP 是典型的问题来源:控制通道走 TCP 1723,数据路径走 GRE,也就是 IP 协议 47。许多家用路由器自带一个只跟踪一条控制连接的 PPTP 助手,于是同一 NAT 后面的第二台客户端打开了控制通道,却完全收不到数据路径。转发编号 47 的 TCP 端口对 GRE 毫无作用,因为 GRE 是协议号而不是端口。

L2TP over IPsec 在设计上就不一样:IKE 使用 UDP 500,NAT 穿透把受保护的载荷移到 UDP 4500,而封装存在的意义正是让一个地址后面的多台客户端都能到达同一个网关。这个设计并不能阻止网关或中间设备按地址设置会话上限,而坐在沙发上看起来,两种失败一模一样。SoftEther 自己的协议也有同类问题:穿透不工作的路由器会放行局域网里的第一台,丢掉第二台。请在两个位置分别测试路由器的 ALG 或穿透开关,因为为旧客户端编写的助手可能破坏当前客户端发出的数据包。

nc -vz 203.0.113.5 1723
sudo tcpdump -ni any proto gre

看起来像传输上限的身份上限

路由器并不是唯一的嫌疑对象,日志能把它和另一种原因区分开。当 OpenVPN 服务器把一个通用名固定到一个隧道地址时,两台设备都会拿到这个地址;没有 duplicate-cn 的话,新会话会把旧会话挤掉。打开这个选项会让两台都保持连接,但它们的身份、证书和吊销决策都只有一份,这比看上去更糟。第二台设备从此无法单独吊销,一个图方便的开关就这样悄悄去掉了你以后可能要用的控制手段。

把服务器的日志和状态文件放在一起读,因为一个记录认证决策,另一个记录当前谁连着。两条共用同一个通用名和一个虚拟地址的记录,说明的是身份撞车而不是路由器上限。商业网关还会叠加自己的限制,比如只允许一个并发会话的套餐、授权数量,或每个公网地址只允许一个会话的规则,这些都不是改路由器能解决的。

sudo journalctl -u openvpn-server@server -n 60 --no-pager
cat /run/openvpn/server.status

把修法对到日志条目上

日志里出现拒绝,就需要给每台设备单独发凭据、向服务提供方申请更高的上限,或者给某一台机器准备第二个网关入口。如果第二次尝试根本到不了服务器,长久的修法是换一台能转发该协议、且能保住多个会话的路由器,或者改用路由器处理得好的传输方式,比如单条 TCP 或 UDP 流。在这两者之间选择,是关于硬件寿命的决定,而不是客户端设置的问题。

不要把能用的设备的配置文件复制到第二台机器上就算完事。那会把连接问题变成权限管理问题,因为丢了一台笔记本之后,再也分不清它和仍在使用的副本。它还会掩盖最初的故障,等第三台设备出现时问题立刻回来。

验证两条活着的会话

让两台设备同时连上,各自运行要用的程序,然后重连其中一台再重复一遍。图标闪一下出现了第二份,并不能证明流量真的走得通;十分钟后掉线的会话是另一个问题,归属也不一样。把服务器最后的报告和用户的观察对一遍,因为这两份说法经常不一致。

如果两条会话都活着并且跑得动流量,修法就站得住,开头写下的那条记录也就成了当时哪里出错的凭据。如果只有一条活着,回到第一步,确认现在落在日志三种结局中的哪一种,因为答案可能已经变了。路由器的助手会掩盖在别的网络上复发的问题,而按地址的限制跟着人走,不跟着设备走。换一个网络再测,是弄清你到底修好了哪一项最便宜的办法。

相关文章