如何防止OpenVPN网络上的TCP连接冻结?


19

在此问题末尾添加了新的详细信息;我有可能正在调查原因。

我在Internet上与少数客户端建立了一个基于UDP OpenVPN的VPN tap模式(我需要,tap因为我需要VPN来传递多播数据包,这似乎对于tun网络来说是不可能的),该模式需要设置。我一直在通过VPN频繁进行TCP连接冻结。也就是说,我将建立一个TCP连接(例如SSH连接,但是其他协议也有类似的问题),并且在会话期间的某个时刻,似乎流量将停止通过该TCP会话进行传输。

这似乎与发生大数据传输的点有关,例如,如果我ls在SSH会话中执行命令,或者我cat的日志文件很长。某些Google搜索在Server Fault上出现了类似于上一个答案的许多答案,表明可能的罪魁祸首是MTU问题:在流量大的时期,VPN试图发送丢包的数据包,这些数据包位于服务器之间。 VPN端点。上面链接的答案建议使用以下OpenVPN配置设置来缓解此问题:

fragment 1400
mssfix

这应该将VPN上使用的MTU限制为1400字节,并固定TCP最大段大小,以防止生成任何大于此大小的数据包。这似乎可以缓解问题,但我仍然经常看到冻结现象。我已经尝试了多种大小作为fragment指令的参数:1200、1000、576,所有结果均相似。我想不出两端之间可能出现这种问题的奇怪的网络拓扑: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.90到目的地的跟踪192.168.100.91。配置两个客户端fragment 1200; mssfix;以尝试限制链接上使用的MTU。以上结果似乎表明它tracepath能够检测到两个客户端之间的1500字节的路径MTU。我会假设由于OpenVPN配置中指定的分段设置,它会稍微小一些。我发现结果有些奇怪。

但是,甚至更陌生:如果我的TCP连接处于停止状态(例如,SSH会话的目录列表在中间冻结),则执行tracepath上面显示的命令会使连接再次启动!对于这种情况,我无法找到任何合理的解释,但是我觉得这可能指向最终解决该问题的解决方案。

有人对其他尝试有任何建议吗?

编辑:我回来了,进一步看了一下,发现只有更多令人困惑的信息:

  • 我将OpenVPN连接设置为1400字节分段,如上所示。然后,我从Internet上连接到VPN,并使用Wireshark查看发生停顿时发送到VPN服务器的UDP数据包。没有一个大于指定的1400字节计数,因此碎片似乎正常运行。

  • 为了验证哪怕一个1400字节的MTU也足够,我使用以下(Linux)命令对VPN服务器执行了ping操作:

    ping <host> -s 1450 -M do
    

    这个(我相信)发送了一个禁用了碎片的1450字节数据包(如果我将其设置为一个明显太大的值(如1600字节),我至少验证了它不起作用)。这些似乎很好用。我从主持人那里得到回复,没有任何问题。

因此,也许这根本不是MTU问题。我只是对可能还有什么感到困惑!

编辑2:兔子洞不断加深:现在,我进一步隔离了问题。它似乎与VPN客户端使用的确切操作系统有关。我已在至少三台Ubuntu计算机(版本12.04至13.04)上成功复制了该问题。只需-放置cat一个大日志文件,我就能在一分钟左右的时间内可靠地复制SSH连接冻结。

但是,如果我使用CentOS 6机器作为客户端进行相同的测试,那么我看不到问题!我已经使用与在Ubuntu计算机上使用的完全相同的OpenVPN客户端版本进行了测试。我可以cat记录文件数小时,而不会看到连接冻结。这似乎提供了有关最终原因的一些见识,但是我不确定那是什么见解。

我已经使用Wireshark检查了VPN上的流量。我不是TCP专家,所以我不确定该如何处理这些细节,但是要点在于,由于Internet链接的带宽有限,UDP数据包有时会被丢弃,从而导致内部的TCP重传VPN隧道。在CentOS客户端上,这些重传正确发生,并且事情进展顺利。但是,在某些情况下,对于Ubuntu客户端,远程端开始一遍又一遍地重传相同的TCP段(每次重传之间的传输延迟都会增加)。客户端向每次重传发送看起来像有效的TCP ACK的消息,但是远端仍继续定期发送相同的TCP段。这将无限期地扩展,并且连接停止。我的问题是:

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

CentOS节点与各个Ubuntu版本之间的一个共同区别是Ubuntu具有更新得多的Linux内核版本(从Ubuntu 12.04中的3.2到13.04中的3.8)。可能指向一些新的内核错误的指针?我假设如果是这样的话,那么我将不是唯一一个遇到问题的人。我认为这似乎不是特别奇特的设置。


tun应该可以通过运行多播路由守护程序(例如pimd让OpenVPN服务器使用--topology设置为“子网” 的选项来在网络上路由多播数据包-参见手册
kostix 2013年

在出现这些问题时,VPN客户端或服务器在日志中是否指示任何内容?
mgorven

@mgorven:绝对不在客户端上。我必须做一些工作才能获取服务器日志。
杰森R

@mgorven:我终于有机会回到这个话题。发生这种情况时,客户端或服务器中的日志什么都没有。真是莫名其妙。
杰森R

1
冻结的客户端是否有可能丢失了丢弃ICMP碎片所需数据包的本地防火墙,而那些没有,没有并且因此正确分段的数据包呢?
MadHatter在2013年

Answers:


10

这个命令为我解决了:

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

您可以使用以下方法验证tun0设置

$ ip a s

干杯!


在客户端或服务器端
马特

非常感谢!@Matt,这取决于问题所在的位置。对我们来说,它在服务器上,但可能在客户端上。值也可能不同,您可以进行测试ping <host> -s 1350 -M do以找到正确的值
Eino Gourdin

2

在TCP中禁用窗口缩放,具有:

sysctl -w net.ipv4.tcp_window_scaling=0

之后,通过VPN到Debian / Ubuntu系统的SSH对我来说工作正常。


0

在使用Putty的Windows上,您必须通过以下方式更改MTU:转到VPN连接的本地连接->网络接口上的详细信息(TAP Windows Adapter或类似的东西)->高级->属性-> MTU(将其更改为某些内容)低于1500)。您可能必须重新连接。它在Windows和Putty上对我有用


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.