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

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

我在两台服务器之间遇到了 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

除了这些 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

服务器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

我注意到的是:

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

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

3.如上所述,我在 OpenVPN 隧道外运行 iperf,吞吐量正常 - 持续约 88Mbps。

我尝试过的:

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

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

3.我在各种论坛上看到关于如何调整 fragment、mssfix 和 mtu-tun 可能有助于提高性能的信息。我尝试了几个变体,如本文,但同样没有任何改善。

有什么想法可能导致 OpenVPN 性能如此差的原因吗?

答案1

经过大量的 Google 搜索和配置文件调整后,我找到了解决方案。我现在的持续速度为 60Mbps,最高可达 80Mbps。它比我在 VPN 之外收到的传输速率要慢一点,但我认为这已经是最好的了。

第一步是设置sndbuf 0服务器rcvbuf 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

如果您使用过 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

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

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

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

答案2

经过几次尝试,我找到了一个很好的解决方案。就我而言,@Elliot 的回复没有帮助。通过谷歌搜索,我发现了这段代码,可以添加到服务器配置中,从而完成这项工作

sndbuf 393216
rcvbuf 393216
push "sndbuf 393216"
push "rcvbuf 393216"

我有一个运行在树莓派3现在我得到了下行速度 71 Mbps,上行速度 16 Mbps。由于 CPU 的性能,下载受到限制。目前,我的配置如下:

client-to-client
duplicate-cn
keepalive 10 120
cipher AES-128-CBC
#cipher AES-256-CBC <<<---- lowers the speed to around 50Mbps, still not bad
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
tun-mtu 9000

OpenVPN 2.4.0 arm-unknown-linux-gnueabihf 和 OpenSSL 1.0.2l

感觉很奇怪,缓冲区的默认配置这样的问题仍然存在。

[编辑]我的 client.ovpn 文件结构如下:

client
dev tun
proto tcp
remote SERVER.IP.ADDRESS.HERE
resolv-retry infinite
nobind
persist-key
persist-tun
mute-replay-warnings
ns-cert-type server
tun-mtu 9000
key-direction 1
cipher AES-128-CBC
comp-lzo
verb 1
mute 20
<ca>
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN RSA PRIVATE KEY-----
[...]
-----END RSA PRIVATE KEY-----
</key>
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
[...]
-----END OpenVPN Static key V1-----
</tls-auth>

答案3

我们有两台相互连接的洲际服务器,它们之间的速度徘徊在 220 Mbit/s 左右。

然而,在 (UDP) OpenVPN 隧道内,速度平均为 21 Mbit/s - 大约慢 10 倍。

(服务器之间存在明显的延迟:大约 130 毫秒,并且使用 TCP 模式下的 Iperf3 测量传输。)

在撰写本文时,尝试了这里所有关于答案的建议,但没有任何帮助。

最终确实有帮助的一件事是:

--txqueuelen 4000

根据 OpenVPN 参考手册:

–txqueuelen n 
(Linux only) Set the TX queue length on the TUN/TAP interface. Currently defaults to 100.

在服务器和客户端上设置此参数后,我也能够在 OpenVPN 隧道下达到相同的“直接链接”速度(~250Mbit/s)。

我已经在使用rcvbuf 0sndbuf 0,但至少独自的,他们根本没有提供任何帮助。

我在以下两篇文章中都发现了这些建议:OpenVPN 论坛中的此页面,并且还在UDPspeeder wiki 中的此页面

另外需要注意的是:我能够使用 iperf 中的 UDP 传输达到更高的速度,但这样做也会导致相当高的数据包丢失。

如果您碰巧需要使用 VPN 在两个有损链路的地方建立隧道,我建议您考虑在 VPN 本身下使用某种前向纠错 (FEC) 隧道。我设法找到并使用的两个隧道是:

  • 之前所提UDP加速器,用于建立 UDP 连接的隧道;
  • 韋普韋,用于建立 TCP 连接隧道;

两者都可以大大减少数据包丢失(首先要花费更多的带宽),甚至最终带来更高的数据吞吐量,即使增加了开销,如果你问我这真的很棒。

(那是因为数据包丢失确实会破坏网络,特别是 TCP请参阅第 6 页。)

出于所有常见的原因,我本来希望在 UDP 上使用 OpenVPN,但我发现当延迟超过 100ms 且速度 >10 Mbit/s 时,使用 UDPspeeder 会很困难。

然而,kcptun 只需要很少的调整就可以很好地工作,实际上真的增加了我们服务器的吞吐量。=)

从长远来看,这里您可以找到有关调整 OpenVPN 性能某些部分的更详细的解释。

答案4

我在日本有一台安装了 openvpn 服务器的 VPS 服务器,而我的客户端连接使用的是纽约的 OpenVPN 客户端模式的 DDWRT。在 100mbit 连接上,我只能获得 1-2mbps。我能优化到的最佳速度是 5mbps,这足以满足我的需求,我相信这是我能做到的最大优化。

我的 OpenVPN 服务器设置:

tun-mtu 9000
sndbuf 393216
rcvbuf 393216
push "sndbuf 393216"
push "rcvbuf 393216"
comp-lzo
txqueuelen 4000
######
port 10111
proto udp
dev tun
user nobody
group nobody
persist-key
persist-tun
keepalive 10 120
topology subnet
server x.x.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "dhcp-option DNS 1.0.0.1"
push "dhcp-option DNS 1.1.1.1"
push "redirect-gateway def1 bypass-dhcp"
dh none
ecdh-curve prime256v1
#tls-crypt tls-crypt.key 0
crl-verify crl.pem
ca ca.crt
cert server_IzA1QdFzHLRFfEoQ.crt
key server_IzA1QdFzHLRFfEoQ.key
auth SHA256
#cipher AES-128-GCM
#cipher AES-128-CBC
#ncp-ciphers AES-128-GCM
#ncp-ciphers AES-128-CBC
#tls-server
#tls-version-min 1.2
#tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256
#tls-cipher TLS-DHE-RSA-WITH-AES-128-CBC-SHA
status /var/log/openvpn/status.log
verb 3

我的 DDWRT OpenVPN 客户端设置也在我的屏幕截图中显示:

tun-mtu 9000
comp-lzo
##########
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
verify-x509-name server_IzA1QdFzHLRFfEoQ name
auth SHA256
auth-nocache
setenv opt block-outside-dns # Prevent Windows 10 DNS leak
verb 3

在此处输入图片描述

在此处输入图片描述

相关内容