在此问题末尾添加了新的详细信息;我有可能正在调查原因。
我在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
设置为“子网” 的选项来在网络上路由多播数据包-参见手册