为什么OpenVPN这么慢?(演义版本)

      8 Comments on 为什么OpenVPN这么慢?(演义版本)

翻译自:http://lowendtalk.com/discussion/40099/why-openvpn-is-so-slow-cool-story#latest

作者:ValdikSS

转载请注明原出处,本出处,以及翻译:cnbeining

我经常看见小白在网上问,为什么用OpenVPN连接两个网站的速度比链接速度慢的多,例如,2Mb/s的链接只有400Kb/s的速度,或者百兆只有20Mb/s的速度。有些人推荐将MTU调大到48000,有些人说应该调整mssfix,但是都不管用。有些人说OpenVPN就这样,老娘就这个速度。扯淡!

一点老黄历

2004年7月。当时发达国家一般家庭网速为256-1024kb/s,在发展中国家网速为56kb/s。Linux2.6.7刚刚发布,带有默认启动TCP窗口大小调节的2.6.8版本一个月前刚发布。OpenVPN已经活跃地开发了3年,即将发布2.0版本。

一名开发者想加入socket缓冲区的代码,估计是想统一各个系统的缓冲区大小。在Windows下,如果人工设置缓冲区大小,网络适配器的MTU会出错,最终是这个结果:

#ifndef WIN32
    o->rcvbuf = 65536;
    o->sndbuf = 65536;
#endif

 

技术层面

如果你用过OpenVPN,你肯定知道OpenVPN支持TCP和UDP。如果你手工设置TCP连接缓冲区大小到64 KB这么小,TCP 窗口大小调整算法不能将窗口大小调节到64K以上。什么意思?假如你的连接水管大但是延迟高,例如从美国到毛子,ping差不多100ms,用默认的OpenVPN设置,你的速度肯定不能高于5.12Mb/s。要50Mb/s的速度,缓冲区至少要640 KB。UDP因为没有窗口大小所以快点,但是也快不到哪去。

怎么破?

你已经猜到了,现在的OpenVPN还在用64 KB的默认缓冲区大小。怎么修?最好的办法是禁止OpenVPN设置自定义缓冲区大小。在服务器和客户端的配置文件加入:

sndbuf 0
rcvbuf 0

 

这样缓冲区大小就由操作系统控制了。对于Linux,这个固定值对于TCP是net.ipv4.tcp_rmem 和net.ipv4.tcp_wmem, UDP是net.core.rmem_default 和 net.core.wmem_default 两个值除2.

如果客户端配置文件不能修改,那么你需要从服务器推送更大的缓存大小:

sndbuf 0
rcvbuf 0
push "sndbuf 393216"
push "rcvbuf 393216”

 

UDP和TCP不同,没有窗口大小这一说,虽然不是整个系统都需要。但是缓冲区过小也有可能降低速度。如果你把缓冲区调成0后还是慢,你应该要么在系统层面增加缓冲区大小(net.core.rmem_default 和 net.core.wmem_default),或者在服务器推送更大的缓冲区配置:

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

 

但是我用Windows!

如果服务器和客户端都是Windows,应该没有这个bug。

附:原文

From time to time, I see people asking for help on forums, who have connected 2 remote sites via OpenVPN and have an awful speed compared to link speed, like 400 Kbit/s with 2 Mbit/s link or 20 Mbit/s with 100 Mbit/s link. Some recommend them to increase MTU on tunnel interface up to 48000, some say they should tune mssfix parameter, but none really helps. Sometimes people say that OpenVPN is so slow because it's userspace and this is its' usual speed. That's Nonsense!
A little bit of history
It's July, 2004. Usual home internet speed in developed countries is 256-1024 Kbit/s, in less developed countries is 56 Kbit/s. Linux 2.6.7 has been released not a long ago and 2.6.8 where TCP Windows Size Scaling would be enabled by default is released only in a month. OpenVPN is in active development for 3 years already, 2.0 version is almost released.
One of the developers decides to add some code for socket buffer, I think to unify buffer sizes between OSes. In Windows, something goes wrong with adapters' MTU if custom buffers sizes are set, so finally it transformed to the following code:

#ifndef WIN32
    o->rcvbuf = 65536;
    o->sndbuf = 65536;
#endif

A little bit of technical info
If you used OpenVPN, you should know that it can work over TCP and UDP. If you set custom TCP socket buffer value as low as 64 KB, TCP Window Size Scaling algorithm can't adjust Window Size to more than 64 KB. What does that mean? That means that if you're connecting to other VPN site over long fat link, i.e. USA to Russia with ping about 100 ms, you can't get speed more than 5.12 Mbit/s with default OpenVPN buffer settings. You need at least 640 KB buffer to get 50 Mbit/s over that link.
UDP would work faster because it doesn't have window size but also won't work very fast.
What should I do?
As you already may guess, the latest OpenVPN release still uses 64 KB socket buffer size. How should we fix this issue? The best way is to disallow OpenVPN to set custom buffer sizes. You should add the following code in both server and client config files:

sndbuf 0
rcvbuf 0

After this, socket buffers would be handled by OS. As for Linux and TCP, this is values from net.ipv4.tcp_rmem and net.ipv4.tcp_wmem and for UDP is a fixed value from net.core.rmem_default and net.core.wmem_default, divided by two.
If you can't change client config, you should push bigger buffer sizes from server:

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

UDP is different from TCP. It doesn't have Window Scale but it doesn't need it OS-wide, but low buffer sizes may slow down it, too. If you think OpenVPN is still slow after changing buffer values to 0, you should either increase OS-wide buffer sizes (net.core.rmem_default and net.core.wmem_default) or increase buffer in server config:

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

But I use Windows!
If you use Windows on both server and client, you should not suffer from this bug.

8 thoughts on “为什么OpenVPN这么慢?(演义版本)

    1. Beining Post author

      没有妹子的人只能大过年翻译技术文章了。。。。。。。。
      (顺便一提 A站那个刺杀金正恩(也就是ACI字幕组版本)的监制是我。。。。所以你知道为什么是这个风格了
      ((论监督对作品的影响

      Reply
  1. pepsi

    最近也遇到一个问题,想问问博主.
    我在公司用路由器搭了一台OPENVPN的服务器,家里也是用的路由器安装的OPENVPN做的客户端,用以访问公司内部资源.
    由于之前家里宽带是10M的,下行速度一般就在1.2M以下.我在家里访问公司内部资源的时候,比如SAMBA访问,速度基本也差不多是10M带宽的的速率.
    然而最近升级了家里带宽到50M,试过在speedtest.net的测速.下行大约60多M,符合50M宽带的速率.然而我走OPENVPN服务访问公司内网的速度基本没有变.
    公司的那台安装OPENVPN服务器的路由器,接入的是100M的宽带,上下行速度都挺高.而我在家里,在电脑上下载东西,通过家里的路由器,速度基本是50M速度的满速率,所以看起来不是宽带问题.
    我现在想的是不是OPENVPN的效率在路由器上有影响了(公司跟家里的路由都用的NETGEAR WNDR3700,还可以的机器,CPU主频是680MHZ的,内存128M的,运行的是OPENWRT系统),就OPENVPN本身的效率来说,我觉得不可能只能这样.我也按你提供的资料,做了相应修改,还是一样的情况.
    你看看还可能是哪里出现了问题呢?我对OPENVPN了解不深入,只会配置起来使用上.谢了~

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *