非常低的 TCP OpenVPN 吞吐量(100Mbit 端口,CPU 利用率低)

Ell*_* B. 29 vpn openvpn

我在两台服务器之间遇到了非常慢的 OpenVPN 传输速率。对于这个问题,我将把服务器称为服务器 A 和服务器 B。

服务器 A 和服务器 B 都运行 CentOS 6.6。两者都位于具有 100Mbit 线路的数据中心,并且 OpenVPN 之外的两个服务器之间的数据传输运行接近约 88Mbps。

但是,当我尝试通过在服务器 A 和服务器 B 之间建立的 OpenVPN 连接传输任何文件时,我的吞吐量大约为 6.5Mbps。

iperf 的测试结果:

[  4] local 10.0.0.1 port 5001 connected with 10.0.0.2 port 49184
[  4]  0.0-10.0 sec  7.38 MBytes  6.19 Mbits/sec
[  4]  0.0-10.5 sec  7.75 MBytes  6.21 Mbits/sec
[  5] local 10.0.0.1 port 5001 connected with 10.0.0.2 port 49185
[  5]  0.0-10.0 sec  7.40 MBytes  6.21 Mbits/sec
[  5]  0.0-10.4 sec  7.75 MBytes  6.26 Mbits/sec
Run Code Online (Sandbox Code Playgroud)

除了这些 OpenVPN iperf 测试之外,两台服务器几乎都处于零负载状态。

服务器 A 被分配了 IP 10.0.0.1,它是 OpenVPN 服务器。服务器 B 被分配了 IP 10.0.0.2,它是 OpenVPN 客户端。

服务器A的OpenVPN配置如下:

port 1194
proto tcp-server
dev tun0
ifconfig 10.0.0.1 10.0.0.2
secret static.key
comp-lzo
verb 3
Run Code Online (Sandbox Code Playgroud)

服务器B的OpenVPN配置如下:

port 1194
proto tcp-client
dev tun0
remote 204.11.60.69
ifconfig 10.0.0.2 10.0.0.1
secret static.key
comp-lzo
verb 3
Run Code Online (Sandbox Code Playgroud)

我注意到的:

1.我的第一个想法是我在服务器上遇到了 CPU 瓶颈。OpenVPN 是单线程的,并且这两台服务器都运行速度不是最快的 Intel Xeon L5520 处理器。但是,我top在其中一个 iperf 测试中运行了一个命令并按下1按内核查看 CPU 利用率,发现每个内核上的 CPU 负载非常低:

top - 14:32:51 up 13:56,  2 users,  load average: 0.22, 0.08, 0.06
Tasks: 257 total,   1 running, 256 sleeping,   0 stopped,   0 zombie
Cpu0  :  2.4%us,  1.4%sy,  0.0%ni, 94.8%id,  0.3%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu1  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu2  :  0.0%us,  0.0%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.3%st
Cpu3  :  0.3%us,  0.0%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu4  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu5  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu6  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu7  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu8  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu9  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu10 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu11 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu12 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu13 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu14 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu15 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    946768k total,   633640k used,   313128k free,    68168k buffers
Swap:  4192188k total,        0k used,  4192188k free,   361572k cached
Run Code Online (Sandbox Code Playgroud)

2.当 iperf 运行时,OpenVPN 隧道上的 Ping 时间会显着增加。当 iperf 未运行时,隧道上的 ping 时间始终为 60 毫秒(正常)。但是当 iperf 正在运行并推动大量流量时,ping 时间变得不稳定。您可以在下面看到在我开始 iperf 测试时的第 4 次 ping 之前的 ping 时间是如何稳定的:

PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=60.1 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=60.1 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=60.2 ms
** iperf test begins **
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=146 ms
64 bytes from 10.0.0.2: icmp_seq=5 ttl=64 time=114 ms
64 bytes from 10.0.0.2: icmp_seq=6 ttl=64 time=85.6 ms
64 bytes from 10.0.0.2: icmp_seq=7 ttl=64 time=176 ms
64 bytes from 10.0.0.2: icmp_seq=8 ttl=64 time=204 ms
64 bytes from 10.0.0.2: icmp_seq=9 ttl=64 time=231 ms
64 bytes from 10.0.0.2: icmp_seq=10 ttl=64 time=197 ms
64 bytes from 10.0.0.2: icmp_seq=11 ttl=64 time=233 ms
64 bytes from 10.0.0.2: icmp_seq=12 ttl=64 time=152 ms
64 bytes from 10.0.0.2: icmp_seq=13 ttl=64 time=216 ms
Run Code Online (Sandbox Code Playgroud)

3.如上所述,我在 OpenVPN 隧道外运行 iperf 并且吞吐量正常 - 始终为 ~88Mbps。

我试过的:

1.我认为压缩可能会造成问题,所以我通过comp-lzo从两个配置中删除并重新启动 OpenVPN来关闭压缩。没提升。

2.尽管我之前发现 CPU 利用率很低,但我认为默认密码可能有点过于密集,系统无法跟上。所以我添加cipher RC2-40-CBC了两个配置(一个非常轻量级的密码)并重新启动了 OpenVPN。没提升。

3.我在各种论坛上阅读了有关如何调整片段、mssfix 和 mtu-tun 可能有助于提高性能的信息。我玩了本文中描述的一些变体,但同样没有改进。

关于什么可能导致 OpenVPN 性能如此糟糕的任何想法?

Ell*_* B. 28

经过大量的谷歌搜索和配置文件调整后,我找到了解决方案。我现在获得了 60Mbps 的持续速度,并突然达到了 80Mbps。它比我在 VPN 之外接收到的传输速率要慢一些,但我认为这已经足够了。

第一步是对组sndbuf 0rcvbuf 0在服务器和客户端OpenVPN的配置。

我在公共论坛帖子(这是俄语原始帖子的英文翻译)上看到建议后进行了更改,我将在此处引用:

现在是 2004 年 7 月,发达国家通常的家庭互联网速度为 256-1024 Kbit/s,欠发达国家为 56 Kbit/s。Linux 2.6.7 发布不久,默认开启 TCP Windows Size Scaling 的 2.6.8 仅在一个月后发布。OpenVPN 已经积极开发 3 年了,2.0 版本即将发布。其中一位开发人员决定为套接字缓冲区添加一些代码,我认为是为了统一操作系统之间的缓冲区大小。在 Windows 中,如果设置了自定义缓冲区大小,适配器的 MTU 会出现问题,因此最终将其转换为以下代码:

#ifndef WIN32
o->rcvbuf = 65536;
o->sndbuf = 65536;
#endif
Run Code Online (Sandbox Code Playgroud)

如果您使用过 OpenVPN,您应该知道它可以通过 TCP 和 UDP 工作。如果您将自定义 TCP 套接字缓冲区值设置为低至 64 KB,则 TCP 窗口大小缩放算法无法将窗口大小调整为超过 64 KB。这意味着什么?这意味着,如果您通过长长的胖链接连接到其他 VPN 站点,即从美国到俄罗斯,ping 大约 100 毫秒,则使用默认的 OpenVPN 缓冲区设置无法获得超过 5.12 Mbit/s 的速度。您至少需要 640 KB 缓冲区才能通过该链接获得 50 Mbit/s。UDP 会工作得更快,因为它没有窗口大小,但也不会工作得非常快。

您可能已经猜到了,最新的 OpenVPN 版本仍然使用 64 KB 套接字缓冲区大小。我们应该如何解决这个问题?最好的方法是禁止 OpenVPN 设置自定义缓冲区大小。您应该在服务器和客户端配置文件中添加以下代码:

sndbuf 0
rcvbuf 0
Run Code Online (Sandbox Code Playgroud)

作者继续描述如果您自己无法控制客户端配置,如何将缓冲区大小调整推送到客户端。

在我做出这些改变之后,我的吞吐率上升到了 20Mbps。然后我发现单个内核上的 CPU 利用率有点高,因此我comp-lzo从客户端和服务器上的配置中删除(压缩)。尤里卡!传输速度跃升至 60Mbps 持续和 80Mbps 突发。

我希望这可以帮助其他人解决他们自己的 OpenVPN 缓慢问题!