如何防止TCP连接通过OpenVPNnetworking冻结?

在这个问题的最后增加了新的细节; 我可能正在调整原因。

我有一个基于UDP的基于OpenVPN的VPNbuild立在互联网上的less数客户端,这些VPN是以tap模式build立的(我需要tap因为我需要VPN来传递多播包,而tunnetworking似乎不可能)。 我一直在经历VPN频繁的TCP连接冻结。 也就是说,我将build立一个TCP连接(例如SSH连接,但其他协议也有类似的问题),并且在会话期间的某个时刻,stream量似乎将停止在该TCP会话上传输。

这似乎与发生大数据传输的点有关,例如,如果我在SSH会话中执行ls命令,或者如果我logging长日志文件。 一些Googlesearch在服务器故障上出现了许多类似于这个问题的答案,表明可能的罪魁祸首是MTU问题:在高stream量期间,VPN试图发送丢弃在VPN端点。 上面链接的答案build议使用以下OpenVPNconfiguration设置来缓解该问题:

 fragment 1400 mssfix 

这应该将VPN上使用的MTU限制为1400字节,并修复TCP最大段大小,以防止产生大于此数据包的数据包。 这似乎缓解了一些问题,但我仍然经常看到冻结。 我已经尝试了一些尺寸作为fragment指令的参数:1200,1000,576,所有的结果都相似。 我想不出两端之间有什么奇怪的networking拓扑可能引发这样的问题:VPN服务器运行在直接连接到Internet的pfSense机器上,而我的客户端也直接连接到另一个位置的Internet。

另外一个奇怪的问题是:如果我运行tracepath工具,那么这似乎可以帮助解决问题。 示例运行如下所示:

 [~]$ tracepath -n 192.168.100.91 1: 192.168.100.90 0.039ms pmtu 1500 1: 192.168.100.91 40.823ms reached 1: 192.168.100.91 19.846ms reached Resume: pmtu 1500 hops 1 back 64 

以上运行在VPN上的两个客户端之间:我发起了从192.168.100.90192.168.100.91目的地的跟踪。 两个客户端都configuration了fragment 1200; mssfix; fragment 1200; mssfix; 试图限制链路上使用的MTU。 上面的结果似乎表明tracepath能够检测两个客户端之间的1500字节的pathMTU。 我会假设由于在OpenVPNconfiguration中指定的碎片设置,它会稍小一些。 我发现结果有点奇怪。

更奇怪的是,如果我有一个处于停顿状态的TCP连接(例如,一个目录列表被冻结的SSH会话),那么执行上面显示的tracepath命令会导致连接重新启动 ! 为什么会出现这样的情况呢,我想不出什么合理的解释,但是我觉得这可能是指向一个解决scheme,最终根除问题。

有没有人有其他的事情可以尝试的build议?

编辑:我回来了,看了一下,发现只有更多的混淆信息:

  • 我将OpenVPN连接设置为1400字节的分段,如上所示。 然后,我通过互联网连接到VPN,并使用Wireshark查看发生故障时发送到VPN服务器的UDP数据包。 没有大于指定的1400字节计数,所以碎片似乎正常运行。

  • 为了validation即使是1400字节的MTU也足够了,我使用下面的(Linux)命令ping VPN服务器:

     ping <host> -s 1450 -M do 

    这(我相信)发送一个1450字节的数据包的分段禁用(我至lessvalidation,它不工作,如果我把它设置为一个明显的太大的值,如1600字节)。 这些似乎工作得很好; 我从主机收到回复没有问题。

所以,也许这根本不是一个MTU问题。 我只是困惑,还有什么可能呢!

编辑2:兔子洞越来越深:我现在已经把问题隔离了一点。 这似乎与VPN客户端使用的确切操作系统有关。 我至less在三台Ubuntu机器(12.04到13.04版本)上成功地复制了这个问题。 我可以在一分钟左右的时间内可靠地复制一个SSH连接冻结,只需input一个大的日志文件即可。

不过 ,如果我使用CentOS 6的机器做客户端的testing,我不会看到问题! 我testing过使用与我在Ubuntu机器上使用的完全相同的OpenVPN客户端版本。 我可以logging几个小时的日志文件,而不会看到连接冻结。 这似乎提供了一些洞察力的最终原因,但我只是不确定是什么洞察力。

我使用Wireshark检查了VPN上的stream量。 我不是一个TCP专家,所以我不知道该怎么做,但是这个要点是,在某些时候,UDP数据包由于Internet链路的有限带宽而被丢弃,从而导致TCP重新传输VPN隧道。 在CentOS客户端,这些重新传输正常发生,事情进展顺利。 然而,在Ubuntu客户端的某个点上,远端开始反复重传相同的TCP段(每次重传之间的传输延迟增加)。 客户端向每个重传发送一个看起来像有效TCP ACK的东西,但是远端仍然会继续周期性地发送相同的TCP段。 这无限扩展了连接,连接失败。 我的问题在于:

  • 有没有人有任何build议如何解决和/或确定TCP问题的根本原因? 就好像对方不接受VPN客户端发送的ACK消息一样。

CentOS节点和各种Ubuntu发行版之间的一个常见区别是Ubuntu有更近期的Linux内核版本(从Ubuntu 12.04的3.2到13.04的3.8)。 指向一些新的内核错误的指针可能? 我假设如果是这样的话,我不会是唯一遇到这个问题的人。 我不认为这似乎是一个特别异国情调的设置。

这个命令为我解决了这个问题:

 $ sudo ip link set dev tun0 mtu 1350 && echo ":)" 

您可以使用validationtun0设置

 $ ip as 

干杯!

在Windows上使用腻子,你必须改变MTU通过转到vpn连接的本地连接 – >networking接口上的细节(TAP的Windows适配器或类似的东西) – >高级 – >属性 – > MTU(改变它的东西低于1500)。 您可能需要重新连接。 它在Windows和腻子上为我工作

在TCP中禁用窗口缩放,其中:

 sysctl -w net.ipv4.tcp_window_scaling=0 

这样做后,通过VPN的Debian / Ubuntu系统的SSH工作正常。

看起来这是一个缓冲问题。 我有同样的问题,我可以通过限制传输速度来避免它。 不是最好的方法,但它可能有助于find一个更好的解决scheme。

请参阅此处的更新1: 如何防止SSH通过openvpn客户端冻结到客户端连接