Windows下OpenVPN的效率问题

2011年11月1日 | 分类: 翻墙相关 | 标签: , , , ,

使用OpenVPN一段时间,发现Windows客户端速度一直远小于Linux客户端。我的网络环境两边都是百兆IPv6共享接 入服务端是OpenVZ VPS。linux下客户端和服务端单个TCP连接速度在500KB/s上下波动,通过OpenVPN后速度差别不大。未优化时,Windows下速度明 显降低,全局下载带宽只能到100KB/s左右。优化后部分问题能够得到明显改善。

OpenVPN有TCP和UDP两种连接方式,虽然OpenVPN over TCP不被推荐

优化Windows TCP接收窗口(RWIN)

作用有二,优化运行于OpenVPN上的TCP连接,在使用TCP模式时优化OpenVPN所使用的TCP连接。这里Vista/Win7无需优化。

Windows下情况有些复杂,对于IPv6 TCP,Vista/Win7没有问题但之前版本Windows处理得很不好。首先Windows Server 2003系统下有个BUG,见KB966321, 简单说被动打开的TCP连接接收窗口大小固定为16384且不随注册表项相应的设定值影响。我发现XP情况更坏,所有IPv6 TCP连接窗口大小都固定为最大44800,在我这里260ms的RTT下,单IPv6 TCP连接的带宽最大只有约160KB/s,该问题尚未解决。微软并未发布Win32 XP平台的补丁。

关于RTT、TCP窗口和最大带宽的关系,在IP数据包没有发生失序的情况下,最大带宽发生在RTT时间内对方发送数据流填满整个TCP接收窗口,比如我的情况,

最大带宽=RWIN/RTT=44800Bytes/260ms=168KB/s,

与实测接近。

Windows下IPv4 TCP也可能存在问题,XP默认没有开启TCP窗口扩大选项,最大窗口限制为65535,往返时间RTT=260ms时,

单TCP连接带宽=65536Bytes/260ms=246KB/s

如何调整窗口大小及开启窗口扩大选项见KB224829,也可用TCP Optimizer,调整后,单TCP连接速度与Linux接近。如上所述,该方法对IPv6 TCP无效。Vista/Win7系列无需修改,窗口扩大选项默认已经打开。

优化OpenVPN接收缓冲区大小

这个优化可以避免Win32下OpenVPN的UDP接口默认缓冲区太小,导致丢包的问题。无论是XP/Vista/Win7,都建议设置。

使用IPv4 UDP或IPv6 UDP模式应该修改rcvbuf,在OpenVPN的配置文件中加入

rcvbuf 65536

rcvbuf最大可取到999999,超过这个值或者未设定,rcvbuf=8192。

rcvbuf选项指Windows UDP套接字的接收缓冲区大小。对OpenVPN速度影响非常明显,尤其对于单核处理器。我的PC是2003年的Pentium 4-M,在优化前整体速度很难超过100KB/s,而此时加上其他应用,CPU使用率还不到30%。优化后与linux下接近(~500KB/s)。设置 过小影响速度的原因可能是内核接收UDP数据包过快填满缓冲区而OpenVPN尚未去读取造成丢包。

设置OpenVPN的mssfix选项

建议设置OpenVPN的mssfix选项,这个选项限制VPN隧道上的TCP连接的MSS(Maximum Segment Size)(OpenVPN的mssfix与TCP的mssfix似乎并不等同,具体还是参考OpenVPN官方文档)。以我的情况为例,服务器端网卡 venet0的MTU为1500,IPv6由TunnelBroker接入,故IPv6最大包长等于1500减去封装其的20字节IP首部等于1480, 再减去IPv6的40字节首部等于1440,然后则减去8字节UDP首部等于1432。若为IPv4 UDP,mssfix等于1500减去20字节IP首部再减去8字节UDP首部等于1472。

#for UDP6
mssfix 1432

#for UDP
mssfix 1472

设置后可防止单个IP片经过OpenVPN时被再次分两个数据包发送。但对于丢包率极低的链路,优化mssfix作用不大。

使用路由表

配合路由表,将需要的流量导入VPN。以前提过动态路由RIP over OpenVPN偶尔会不稳定,建议还是使用静态路由:

1route.exe -p ADD 8.0.0.0 MASK 252.0.0.0 10.8.0.5 METRIC 40

要求服务端配置文件使用ccd固定每个客户的IP地址与网关地址,

client-config-dir ccd

服务器ccd文件夹下建立clinet1,内容:

1ifconfig-push 10.8.0.6 10.8.0.5

当VPN连接时,静态路由由于TAP-Win32设备的打开而自动生效,关闭时相应静态路由不起作用,仍使用原路由/默认网关。静态路由保存于注册表

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\PersistentRoutes

不随接口启动/断开或关机而消失。

几个细节

无论是服务端还是客户端,OpenVPN的verb选项都不应过大,verb提供Debug信息,过大可能导致Debug信息的写入占用过多磁盘IO或者CPU资源。

开启comp-lzo,本身针对数据包的lzo的压缩率并不好,但是如果大量空白数据在传输的话,作用还是非常明显的。

OpenSSL加密与LZO压缩的影响(2011年1月2日更新)

对于不是特别古老的CPU,这两项都不会成为性能瓶颈。然而:

(1)VPS等环境下,cpu被共享,服务器能用于压缩和加密的计算资源不多
(2)客户端设备繁多,可能存在性能瓶颈。

对SSL,OpenVPN先查看可用的加密方法:

1openvpn --show-ciphers

注意区别于

1openvpn --show-tls

后者是指在交换密钥时用到的加密方法,而前者是指对于数据通道的加密方法。前者真正影响传输性能。

速度比较快的加密方法也只有bf-cbc和aes-128-cbc两种。然后分别在服务端和客户端进行一下OpenSSL性能测试,Win下的OpenSSL在OpenVPN安装目录下的bin文件夹内。

1openssl speed bf-cbc aes-128-cbc

根据实际速度选择合适的加密算法,然后在服务器和客户端的openvpn配置文件中用cipher BF-CBC或者cipher AES-128-CBC指明,服务端和客户端配置文件都需要更改。注意部分Intel i5/i7和AMD的Bulldozer处理器支持AES-NI指令集,搭配OpenSSL的AES-NI补丁可以将AES-128-CBC的速度提升7倍。

对lzo我没有找到简单科学的的测试方法,我的测试方法是运行

1dd count=10240 if=/dev/urandom | lzop -c >/dev/null

然后把上面的结果处以top里面看到的lzop的cpu占用率,得到lzop真实效率。在我的测试中,Xeon(R) CPU X3220@2.40GHz的一个核心上,占用14%的cpu时间,只能处理5.0MB/s的压缩。官方的数据在这里

意义

不使用OpenVPN时,下载有多线程工具,视频网站有CDN加速,RWIN和RTT的限制都被很好地避免了。然而OpenVPN需要将所有流量全部经由单个UDP/TCP连接传输,保证单个接口/连接的吞吐率就非常重要了。

原文http://www.lostriver.net/efficiency-problem-on-win32-openvpn/

廉价VPS用来翻墙又如何一文中,有网友说使用的VPS用ssh翻墙速度很快而openvpn速度很慢,正好在网络上看到这篇文章就转载过来给大家参考了。

据测试,增加rcvbuf 65536和mssfix 1472参数后,openvpn速度有小幅提升,使用aes-128-cbc加密比默认的bf-cbc加密稍快一些,aes-256-cbc加密速度就很悲剧了,当然没有特殊要求一定要用udp模式啦。

  1. 地板
    2011年11月1日15:40

    你的地盘很火当然要抢了

  2. 板凳
    2011年11月1日15:11

    我是来抢板凳的

    • iGFW
      2011年11月1日15:14

      呵呵,这个还要抢

  3. 小z
    2011年11月1日14:10

    沙发!先抢了再看!

    • iGFW
      2011年11月1日14:19

      呵呵,你要自己去个名字啊