VPN 提供的 IPSec 服务在访问某些网站时会出现一直无法载入的问题(例如 nodejs.org 载入的资源 http://use.typekit.net/mse5tqx.js),经查是这些网站忽略了 MTU 超大带来的 ICMP Port Unreachable 消息。OpenVPN 之所以不存在这个问题,是因为我们把 MTU 设为较保守的 1356;而 IPSec 没有提供设置 MTU 的选项,默认 MTU 为 1380,而事实上可用的 MTU 只有 1374。用户发送的 TCP 连接请求中的 MSS 被设为 1360(=1380-20),也就是允许网站服务器在每个 TCP 包中包括 1360 字节的数据。网站服务器返回这种塞不进 IPSec 包的超大数据包时,IPSec 接入服务器会丢弃此数据包并返回 ICMP Port Unreachable 错误消息。正常情况下网站服务器收到此种错误消息,会以 ICMP 消息中附带的最大包长重新发送数据,但某些网站没有遵守标准,导致 URL 无法访问。

为此我们在 LUG VPN 访问外网的网关上做了如下配置,“篡改” 用户发送的 TCP “连接请求”(SYN)中的 MSS 字段为 1354(=1374-20),并不超过下一跳路径所允许的最大值。这样网站服务器就不会发送超大数据包了。


iptables -A FORWARD -s 10.5.0.0/16 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1354
iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu