修公司的VPN修了一整天
背景
公司的 VPN 是为了访问内网资源,并且对每个 IP 和账号做了不同的权限控制。
最近公司的 VPN 老是断连,刚连上去半个小时就给我断了,然后我就被安排修了。
环境
先看一眼环境:
CentOS 7 (kernel 3.10.0-1160) + Libreswan 3.25 (pluto) + xl2tpd + pppd
WARNING
大家也可以想到,CentOS 7 的 yum 下载的东西新不到哪里去。Libreswan 现在应该都 5 版本了,这还是 3.25 呢。听同事说,他们当初搭这个 VPN 服务器的时候尝试了很多方案,很多新特性都支持不了。
问题一:频繁断连
因果链分析
主要因果链如下:
options.xl2tpd 缺少 LCP echo 配置
↓
隧道空闲时无心跳包发送
↓
公司路由器 NAT UDP 会话映射超时(约 60 秒),端口映射被清除
↓
IPsec SA(UDP 4500)失效,客户端检测到连接中断
↓
客户端发起 SA 重协商(每 ~60 秒一次,日志已证实)
↓
新 SA 建立 → 又空闲 60 秒 → NAT 又超时 → 又 rekey(死循环)
↓
某次 rekey 碰到网络抖动 → rekey 失败
↓
keyingtries=3 已耗尽 + dpdaction=clear 不重连 → 彻底断开
修改 options.xl2tpd
增加 LCP 保活心跳,每 10 秒发送一次(远小于 NAT 60 秒超时):
+ lcp-echo-interval 10
+ lcp-echo-failure 3
nodefaultroute
| 参数 | 值 | 说明 |
|---|---|---|
lcp-echo-interval | 10 | 每 10 秒发一次 LCP Echo-Request 心跳包 |
lcp-echo-failure | 3 | 连续 3 次(30 秒)无 Echo-Reply 才判定断开 |
修改 ipsec.conf
- keyingtries=3
+ keyingtries=%forever
- dpdaction=clear
+ dpdaction=restart
| 参数 | 修改前 | 修改后 | 说明 |
|---|---|---|---|
keyingtries | 3 | %forever | 无限重试,不轻易放弃 |
dpdaction | clear | restart | 掉线后自动重连 |
结果
测试了几个小时都没有发生断连,第一个问题解决。
TIP
但是除非有其他设备在连,这就会触发第二个问题。
问题二:NAT 环境下设备抢占
这个协议对 NAT 设备不友好,会和其他设备抢占端口,一个 NAT 环境下只有一个设备可以连接上。
INFO
为什么必须是 NAT 设备呢?太简单了就不解释了。
为什么之前要用 IKEv1?因为软件太老了,很多方便的东西不支持。
解决方案:切换到 IKEv2
我用的是 IKEv2,但是:
- Windows 内置的 VPN 客户端不支持 IKEv2 + PSK
- Libreswan 3.25 不支持 IKEv2 + EAP-MSCHAPv2
- 最后只能用 IKEv2 + 证书
WARNING
真的超级麻烦,明明账号密码新版早就支持了,PSK 也早就支持了,就是用不了,真是无解了。
踩过的坑
坑一:连上 VPN 没网了
明明在服务端设置了分流模式,看了半天。然后 GPT 给我看了一下,说我客户端是全隧道模式,真是给我蠢爆了。
坑二:证书验证通过但同事连不上
我导入证书验证连接通过了,但是同事通过不了,直接让 AI 写了一个脚本运行批量导入。
总结
TIP
如果是 Ubuntu 最新版该多好呀,那就好多都可以用了。
- 断连问题:核心原因是缺少 LCP 保活心跳,加上 NAT 超时导致的死循环,通过配置
lcp-echo-interval和dpdaction=restart解决 - NAT 抢占问题:IKEv1 协议天然对 NAT 不友好,升级到 IKEv2 + 证书认证解决
- 老系统是原罪:CentOS 7 + Libreswan 3.25 限制了太多选项,能升级就升级
