OpenVPN性能-当tap遇到bonding

一.引子

别的就不多说什么了,前面的文章说过,OpenVPN有两个瓶颈,一个是tap网卡,另一个是加密/解密 ,然而不可否认,OpenVPN的客户端和服务器端处于一个“虚拟网段”,抛开虚拟不谈,只要是一个网段的,我们就可以说它们属于一个局域网(当然前提是使用tcp/ip网络),既然属于一个局域网,那么它要么是广播的,要么是点对点的,不管怎样,两端都有确定的三层地址(IP地址),所有的数据包都是通过这个三层地址来传输到对端的,因此为了使得路径畅通,我们只关心路由即可。
既然是链路层网络(即使它是虚拟的,我们称为EoTAP-Ethernet Over Tap) ,我们就可以使用链路层的端口聚合来增加带宽或者加强稳定性,类似一个局域以太网的两台机器可以直连或者通过交换机间接相连,OpenVPN的服务器和客户端也可以被认为是通过tap网卡连接的“虚拟局域网”,那么它们之间的连接也可以使用端口聚合。
对于OpenVPN来讲,VPN链路的“虚拟物理链路”其实就是两个OpenVPN进程(OpenVPN客户端和服务器)之间的真实物理链路(我们知道,从tap网卡发出的数据进入了tap字符设备,然后进入OpenVPN进程,随着OpenVPN进程间的真实物理链路到达对端,然后进入tap字符设备,最终被tap接收...),因此我们完全可以将4个OpenVPN进程绑成两个虚拟链路通道。
对于负载均衡策略来讲,同一链路层(不管是点对点网络还是广播网络)网段使用端口聚合的方式,而网络层的负载均衡需要使用分割网段的方式。对于OpenVPN连接的两端,不管它们跨越了多少物理链路层网段,由于存在于同一个虚拟链路层网段,它们就适合用端口聚合的方式进行负载均衡,这里的“端口”就是OpenVPN进程。
如果你的机器拥有16核的cpu或者16个cpu以及8257X或者8259X的网卡芯片,对端也拥有同样的配置,仅开启一对OpenVPN进程的话,大量的资源将被无情浪费,这是OpenVPN本身造成的,它是单进程单线程程序,无法利用多核cpu,tap网卡一帧一帧的处理方式和物理网卡芯片的能力严重不匹配,由于tap的处理方式,物理网卡也要一帧一帧发送(这些帧和tap出来的帧的区别仅仅在于它将数据加密处理后加了一层tcp/ip协议栈的封装),因此何不启用16对OpenVPN进程,一个cpu上绑一个,然后在每一端将16个OpenVPN进程打开的tap网卡全部绑定在一起,这样不就相当于16个端口聚和了吗?
二.环境 
1.服务器端的OpenVPN配置文件server1/2.cfg: 
dev tun
proto tcp
tls-server
cipher BF-CBC
keepalive 10 60
mode server
server 172.16.0.0 255.255.0.0
local 0.0.0.0
lport 1194
dh dh1024.pem.dh
ca ca.pem
cert server.pem
key  server.key
配置文件2仅将lport改为1195即可
2.客户端OpenVPN配置文件client1/2.cfg: 
client
float
dev tun
proto tcp
remote 192.168.1.22 1194
ca ca.pem
cert client.pem
key  client.key
cipher BF-CBC

配置文件2仅将remote的端口改为1195即可
3.内核为2.6.32,bonding支持sysfs的配置方式 
4.备注:
4.1. 之所以使用tun模式而不是tap模式是因为OpenVPN服务器进程作为一个虚拟的交换机对arp有所过滤,因此需要修改一些OpenVPN的代码后才能更好更稳定的支持bonding,否则只能使用bonding的active-backup模式,且fail_over_mac参数也要设置。tun模式就不存在这个问题,它不发arp,只是点对点,有路由即可。
4.2. 多个OpenVPN服务器的虚拟ip必须一致,且保证这些OpenVPN服务器一对一的分配给同一台机器的所有OpenVPN客户端的虚拟也必须一致,因为OpenVPN服务器要验证客户端ip地址的,bonding了之后,所有的客户端将统一于唯一的一个ip地址。
4.3. 为何使用2.6.32的内核,实际上如果使用2.6.8这么老的内核用本文的方式是配不通的,因为老的内核没有使用sysfs配置bonding,而是使用了ioctl,这样的话,由于tap网卡驱动不支持bonding相关的ioctl参数,那一切都是没有意义,这里也体现了ioctl地狱是真实存在的。需要各方面联合才行,为了支持bonding,不得不修改tap驱动,增加其ioctl参数。
三.配置 
1.在服务器上启动两个OpenVPN:
root@zyxx:~/vpn# openvpn --config server1.cfg
root@zyxx:~/vpn# openvpn --config server2.cfg
2.在客户端上启动两个OpenVPN:
root@zyxx:~/vpn# openvpn --config client1.cfg
root@zyxx:~/vpn# openvpn --config client2.cfg
3.配置服务器端bonding:
3.1.载入bonding模块
root@zyxx:~/vpn#modprobe bonding
3.2.配置bond0:
root@zyxx:~/vpn#echo +bond0 > /sys/class/net/bonding_masters
3.3.首先down掉所有的tap网卡:
root@zyxx:~/vpn# ifconfig tun0 down
root@zyxx:~/vpn# ifconfig tun1 down
3.4.将所有的tap网卡加入bond0:
root@zyxx:~/vpn# echo +tun0 > /sys/class/net/bond0/bonding/slaves
root@zyxx:~/vpn# echo +tun1 > /sys/class/net/bond0/bonding/slaves
3.5.配置mode及miimon链路检测:
root@zyxx:~/vpn# echo 0 > /sys/class/net/bond0/bonding/mode
root@zyxx:~/vpn# echo 100 > /sys/class/net/bond0/bonding/miimon
将mode设置成了简单round-robin负载均衡模式。
3.6.配置bond0的ip:
root@zyxx:~/vpn# ifconfig bond0 172.16.0.1/16
3.7.删除冲突路由,仅仅保留bond0的路由:
root@zyxx:~/vpn# route del -host 172.16.0.2 dev tun0
root@zyxx:~/vpn# route del -host 172.16.0.2 dev tun1
root@zyxx:~/vpn# route del -host 172.16.0.6 dev tun0
root@zyxx:~/vpn# route del -host 172.16.0.6 dev tun1
root@zyxx:~/vpn# route add -host 172.16.0.6 dev bond0
这里假设分配给拥有client.pem这个证书的客户端的ip是172.16.0.6
3.8.OK
4.配置客户端的bonding:
同3
四.感受 
1. 和没有使用bonding相比,找一个测速工具看一下通过bonding之后的OpenVPN是否速度加倍了,答案是效果可能不明显;
2. 效果不明显可能因为你的机器配置不是很好,OpenVPN并没有明显的降速,也就是说,通过OpenVPN链路和通过物理链路的速率相差不大。那样的话就在客户端启动的时候加上--shape参数,手工将单个OpenVPN虚拟链路的速率降低,这样效果就明显了;
3. 我使用:openvpn --config client1/2.cfg --shaper 5000启动OpenVPN客户端,wget的速率达到了6k/s左右(OpenVPN服务器和客户端之间属于不同的VLAN),而使用单个OpenVPN链路的话速率仅仅是2.5k~3k/s左右。
4. 目前OpenVPN还不支持直接配置bonding,期待有人做相关的修改,使之可以bonding。这个修改很简单,不需要修改驱动,其实只需要将上述的配置过程写成自动化的即可,也就是增加几个参数的工作量,如果有人觉得有趣,不妨试一下,如果没有人试,没有人试就算了...
五.后记 
前一段时间,工作原因需要测试OpenVPN的性能,我对此工作任务非常感兴趣,期待最终能得到一个结果,虽然我对OpenVPN的ssl+tap架构十分满意,然而却对它的单线程架构,每帧传输实在不敢恭维,多核当道的今天,网卡芯片普遍offload的今天,OpenVPN好像是十几年前的家伙...
我并不期待得到的结果一定是好的,实际上我需要的quick success或者quick failure,二者都令我满意,最重要的是在工作过程中得到了锻炼,这个过程不管对个人还是对公司都是一个很有意义的东西。期间,我百度,google了很多资料,大多数都是关于OpenVPN本身参数配置的,很少有关于修改tap驱动在降低些许延迟的小代价下提高吞吐量的,也几乎没有将tap网卡做bonding的,甚至连加密算法对OpenVPN性能的影响的资料都是少之又少,因此我就我的经验写了几篇文章,发表在CSDN上,这几篇文章都是以《OpenVPN性能》 为主标题,副标题根据文章内容而变化,分享给需要的人们,希望以后有谁遇到类似的问题再google和百度的时候,能得到一些新鲜的东西 。同时也小小呼吁一下分享精神,当然前提是不泄露公司和个人的隐私哦...

标签: 无
返回文章列表 文章二维码
本页链接的二维码
打赏二维码
评论列表
  1. [...]在列出真的实现之前,先考虑另一种替代方案,这种方案不需要修改任何东西,那就是运行多个OpenVPN实例,然后将它们的tap网卡bonding在一起,注意这种方案使用了bonding驱动,而bonding驱动只适用于以太网场合,这就意味着你不能使用tun网卡了,而tun网卡不需要以太网封装,没有arp等链路层地址解析,效率更高些,这就产生了一个矛盾,然而也能带来一些性能提升,具体操作可参见《Open[...]

  2. [...]5. OpenVPN性能-当tap遇到bonding[...]

添加新评论