经常在论坛上看到对多拨之后带宽无法叠加的抱怨。经过一段时间的研究,发现目前主流有三种工具来帮助我们实现多WAN带宽叠加,分别是:
- multiwan(来自于openwrt官方package,https://dev.openwrt.org/browser/packages/net/multiwan)
- m-route(来自xwrt项目的扩展package,http://x-wrt.googlecode.com/svn/trunk/package/m-route/)
- nwan(国产,http://openwrt.8800.org/nwan.ipk)
- mwan2(来自openwrt论坛,http://213.136.13.52/mwan2_1.3-10.tar.gz)
而且更有高手能够不使用以上工具,而直接使用linux的网络命令配置出同样的多WAN带宽叠加的效果。那么到底用何种工具,如何配置才能真正叠加带宽呢?为了回答这个问题,我们需要动手来做实验。在实践来检验工具和方案的效果,并且进一步了解工具背后的原理。
实验环境
使用实际的物理机和路由器来实验是非常困难的。为了保证实验能够准确(不受实际带宽的干扰)并且成本低(不需要来回走动,使用多台机器),我们需要使用vmware的虚拟机,在x86的OpenWRT平台上来完成这个实验。下面是我们首先建立的一个环境的网络拓扑图:
在lab-sleepy上启动了一个nginx进程,监听8080端口,提供了一个1.bin文件供客户端下载。
在lab-doc上执行curl http://10.2.0.100:8080/1.bin -o 1.bin,可以看到限速是成功的,大概就是7kb/s(合56kbps)。
1 root@lab-doc:/usr/share/download# curl http://10.2.0.100:8080/1.bin -o 1.bin 2 % Total % Received % Xferd Average Speed Time Time Time Current 3 Dload Upload Total Spent Left Speed 4 0 119M 0 114k 0 0 6225 0 5:34:50 0:00:18 5:34:32 4194
在lab-doc上执行traceroute 10.2.0.100可以看到中间经过的两个路由器
1 root@lab-doc:/usr/share/download# traceroute 10.2.0.100 2 traceroute to 10.2.0.100 (10.2.0.100), 30 hops max, 38 byte packets 3 1 10.0.0.2 (10.0.0.2) 0.413 ms 0.265 ms 0.259 ms 4 2 10.1.2.2 (10.1.2.2) 0.609 ms 0.445 ms 0.421 ms 5 3 10.2.0.100 (10.2.0.100) 0.625 ms 0.536 ms 0.491 ms
在lab-bashful上执行ip route可以看到这个时候家庭路由器的路由状态,有三条独立的出口。
1 root@lab-bashful:~# ip route 2 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2 3 10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.100 4 10.1.1.0/24 dev eth2 proto kernel scope link src 10.1.1.100 5 10.1.2.0/24 dev eth3 proto kernel scope link src 10.1.2.100 6 default via 10.1.2.2 dev eth3 7 default via 10.1.1.2 dev eth2 8 default via 10.1.0.2 dev eth1
多WAN带宽合并的目标就是把这三条独立的出口合并成一条来使用,使得总带宽可以56kbps * 3达到168kbps,实际下载速度从7kb/s提升到21kb/s。
实验:使用multiwan叠加带宽(模式Compatibility Balancer,不同出口网关,相同目标服务器)
在lab-bashful上安装multiwan。配置文件如下:
1 root@lab-bashful:~# cat /etc/config/multiwan 2 3 config 'multiwan' 'config' 4 option 'default_route' 'balancer' 5 6 config 'interface' 'wan1' 7 option 'weight' '10' 8 option 'health_interval' '10' 9 option 'timeout' '3' 10 option 'health_fail_retries' '3' 11 option 'health_recovery_retries' '5' 12 option 'failover_to' 'balancer' 13 option 'dns' 'auto' 14 option 'icmp_hosts' 'gateway' 15 16 config 'interface' 'wan2' 17 option 'weight' '10' 18 option 'health_interval' '10' 19 option 'timeout' '3' 20 option 'health_fail_retries' '3' 21 option 'health_recovery_retries' '5' 22 option 'failover_to' 'balancer' 23 option 'dns' 'auto' 24 option 'icmp_hosts' 'gateway' 25 26 config 'interface' 'wan3' 27 option 'weight' '10' 28 option 'health_interval' '10' 29 option 'timeout' '3' 30 option 'health_fail_retries' '3' 31 option 'health_recovery_retries' '5' 32 option 'failover_to' 'balancer' 33 option 'dns' 'auto' 34 option 'icmp_hosts' 'gateway'
重启路由器,确保multiwan启用之后,执行ip route查看路由规则是否有变化
1 root@lab-bashful:~# ip route 2 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2 3 10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.100 4 10.1.1.0/24 dev eth2 proto kernel scope link src 10.1.1.100 5 10.1.2.0/24 dev eth3 proto kernel scope link src 10.1.2.100 6 default via 10.1.2.2 dev eth3 7 default via 10.1.1.2 dev eth2 8 default via 10.1.0.2 dev eth1
不曾见到路由规则发现变化,但是观察iptables,发现多了许多规则。最明显之处在于这三条规则
Rule# | Pkts. | Traffic | Target | Prot. | Flags | In | Out | Source | Destination | Options |
1 | 0 | 0.00 B | FW1MARK | all | -- | * | * | 0.0.0.0/0 | 0.0.0.0/0 | mark match 0x2 statistic mode random probability 0.330000 |
2 | 0 | 0.00 B | FW2MARK | all | -- | * | * | 0.0.0.0/0 | 0.0.0.0/0 | mark match 0x2 statistic mode random probability 0.500000 |
3 | 0 | 0.00 B | FW3MARK | all | -- | * | * | 0.0.0.0/0 | 0.0.0.0/0 | mark match 0x2 statistic mode random probability 1.000000 |
看来mulitwan的compatibility balancer是用iptables实现的multiwan,而不是路由表。
使用curl单线程下载,速度无变化。多个curl下载,总带宽也不见涨。
为什么呢?我们来看看multiwan在compatibility balancer模式下到底干了什么。
实验:无叠加脚本,系统默认行为
先把multiwan删掉,看看干净的OpenWRT在三个default route出口的情况下,行为是怎样的。
1 root@lab-bashful:~# ip route 2 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2 3 10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.100 4 10.1.1.0/24 dev eth2 proto kernel scope link src 10.1.1.100 5 10.1.2.0/24 dev eth3 proto kernel scope link src 10.1.2.100 6 default via 10.1.2.2 dev eth3 7 default via 10.1.1.2 dev eth2 8 default via 10.1.0.2 dev eth1 9 10 root@lab-doc:/usr/share/download# traceroute 10.2.0.100 11 traceroute to 10.2.0.100 (10.2.0.100), 30 hops max, 38 byte packets 12 1 10.0.0.2 (10.0.0.2) 0.225 ms 0.174 ms 0.190 ms 13 2 10.1.2.2 (10.1.2.2) 0.351 ms 0.339 ms 0.282 ms 14 3 10.2.0.100 (10.2.0.100) 0.383 ms 0.293 ms 0.262 ms 15 16 root@lab-bashful:~# ip route show cache | grep 10.2.0.100 17 10.2.0.100 from 10.0.0.100 via 10.1.2.2 dev eth3 src 10.0.0.2 18 10.0.0.100 from 10.2.0.100 dev eth0 src 10.1.2.100
重复实验几次,仍然是一样的。这个状态就和很多朋友遇到的情况一样,在多WAN脚本没有生效的状况下,流量只会从最后拨上的WAN出口走,这个例子里就是总是从WAN3出去。
实验:使用multiwan叠加带宽(模式Compatibility Balancer,不同出口网关,相同目标服务器)
重新把multiwan装上,看看traceroute是否发生变化
1 root@lab-doc:/usr/share/download# traceroute 10.2.0.100 2 traceroute to 10.2.0.100 (10.2.0.100), 30 hops max, 38 byte packets 3 1 10.0.0.2 (10.0.0.2) 0.218 ms 0.122 ms 0.082 ms 4 2 10.1.1.2 (10.1.1.2) 0.204 ms 0.141 ms 0.156 ms 5 3 10.2.0.100 (10.2.0.100) 0.488 ms 0.273 ms 0.386 ms 6 7 root@lab-bashful:~# ip route show cache | grep 10.2.0.100 8 10.2.0.100 from 10.0.0.100 via 10.1.1.2 dev eth2 src 10.0.0.2 9 10.0.0.100 from 10.2.0.100 dev eth0 src 10.1.1.100
可以发现,走的路由是eth2而不是eth3。重复执行traceroute无变化,执行ip route flush cache之后,路由会发生变化。
1 root@lab-bashful:~# ip route flush cache 2 3 root@lab-doc:/usr/share/download# traceroute 10.2.0.100 4 traceroute to 10.2.0.100 (10.2.0.100), 30 hops max, 38 byte packets 5 1 10.0.0.2 (10.0.0.2) 0.198 ms 0.150 ms 0.146 ms 6 2 10.1.2.2 (10.1.2.2) 0.314 ms 0.261 ms 0.170 ms 7 3 10.2.0.100 (10.2.0.100) 0.349 ms 0.303 ms 0.249 ms
由此可见,multiwan不是什么都没做的,至少不同的出口路由,在路由规则没有被缓存的情况下,是有一定可能性被系统选择使用的。每次执行完curl 之后,在lab-bashful上执行一次ip route flush cache,再次执行curl有一定概率走另外一条WAN。
实际上multiwan在Comptability模式的LoadBalancer下,不仅仅使用了iptables,还有使用了自己的路由表。
第一步:
Chain MultiWanRules (References: 1)
Rule # Pkts. Traffic Target Prot. Flags In Out Source Destination Options
1 2627 173.36 KB LoadBalancer all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x0
第二步:
Chain LoadBalancer (References: 1)
Rule # Pkts. Traffic Target Prot. Flags In Out Source Destination Options
1 2715 180.58 KB MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x1
2 2715 180.58 KB CONNMARK all -- * * 0.0.0.0/0 0.0.0.0/0 CONNMARK save
第三步:
root@lab-bashful:~# ip rule
0: from all lookup local
9: from all fwmark 0x1 lookup LoadBalancer
10: from 10.1.0.100 lookup MWAN1
11: from all fwmark 0x10 lookup MWAN1
20: from 10.1.1.100 lookup MWAN2
21: from all fwmark 0x20 lookup MWAN2
30: from 10.1.2.100 lookup MWAN3
31: from all fwmark 0x30 lookup MWAN3
32766: from all lookup main
32767: from all lookup default
第四步:
root@lab-bashful:~# ip route show table LoadBalancer
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2
10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.100
10.1.1.0/24 dev eth2 proto kernel scope link src 10.1.1.100
10.1.2.0/24 dev eth3 proto kernel scope link src 10.1.2.100
default proto static
nexthop via 10.1.0.2 dev eth1 weight 10
nexthop via 10.1.1.2 dev eth2 weight 10
nexthop via 10.1.2.2 dev eth3 weight 10
所以实现的方式是先用iptables给packet打上标记,0x1。然后在全局路由表里设置规则,所有打了0x1标记的包,都走独立的名叫 LoadBalancer的路由表,然后在LoadBalancer这个路由表里设置一条多出口的default route并设置权重(weight)。Linux内核会根据权重来选择具体走哪条路由。
目前我所看见的所有的多WAN叠加脚本的原理都是一样的。在连接建立的时候,由路由器来选择一条路由。因为default路由是nexthop的形式,所 以会这个连接用WAN1,下一个连接走WAN2。连接建立了之后,这个出口不能更改的(原因可能是因为NAT的需要)。由于路由表有缓存,所以对于同一个 目标IP,一旦走了某个特定的WAN,比如WAN1,之后对于所有指向这个目标IP的请求都只会走WAN1,因为default路由只有在缓存中没有匹配 的路由路径的时候才起作用。所以我们需要用ip route flush cache来使得第二次curl走不同的WAN。或者用morfast的办法 http://www.morfast.net/blog/linux/load-balance/ 修改内核参数禁用路由缓存。
1 root@lab-bashful:~# echo -1 > /proc/sys/net/ipv4/rt_cache_rebuild_count 2 3 root@lab-doc:~# traceroute 10.2.0.100 4 traceroute to 10.2.0.100 (10.2.0.100), 30 hops max, 38 byte packets 5 1 10.0.0.2 (10.0.0.2) 0.222 ms 0.144 ms 0.138 ms 6 2 10.1.2.2 (10.1.2.2) 0.283 ms 10.1.1.2 (10.1.1.2) 0.256 ms 0.287 ms 7 3 10.2.0.100 (10.2.0.100) 0.505 ms 0.398 ms 0.355 ms 8 root@lab-doc:~# traceroute 10.2.0.100 9 traceroute to 10.2.0.100 (10.2.0.100), 30 hops max, 38 byte packets 10 1 10.0.0.2 (10.0.0.2) 0.223 ms 0.179 ms 0.168 ms 11 2 10.1.1.2 (10.1.1.2) 0.403 ms 0.353 ms 0.255 ms 12 3 10.2.0.100 (10.2.0.100) 0.378 ms 0.392 ms * 13 14 router@router-dev:~/Downloads$ aria2c -x4 -s4 -j4 http://10.2.0.100:8080/1.bin 15 [#1 SIZE:5.2MiB/119.2MiB(4%) CN:4 SPD:20.4KiBs ETA:1h35m12s]
由此可见通过修改内核参数,可以使得相同目标IP,建立不同连接也走不同的WAN。
实验:使用multiwan叠加带宽(模式Fast Balancer,不同出口网关,相同目标服务器)
这次我们把multiwan设置为Fast Balancer。其实现方式就不再是ip route nexthop了,变成了用iptables来实现选择性路由。
第一步:
Chain MultiWanRules (References: 1)
Rule # Pkts. Traffic Target Prot. Flags In Out Source Destination Options
1 21838 1.46 MB FastBalancer all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x0
之前在这里的Target是LoadBalancer。
第二步:
Chain FastBalancer (References: 1)
Rule # Pkts. Traffic Target Prot. Flags In Out Source Destination Options
1 21838 1.46 MB MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x2
2 21838 1.46 MB CONNMARK all -- * * 0.0.0.0/0 0.0.0.0/0 CONNMARK save
之前LoadBalancer设置的是0x1。
第三步:
Chain MultiWanLoadBalancer (References: 1)
Rule # Pkts. Traffic Target Prot. Flags In Out Source Destination Options
1 7166 490.46 KB FW1MARK all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x2 statistic mode random probability 0.330000
2 7296 499.04 KB FW2MARK all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x2 statistic mode random probability 0.500000
3 7376 504.89 KB FW3MARK all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x2 statistic mode random probability 1.000000
第一条规则是1/3的概率,第二条是剩下的50%,也就是总的1/3,最后100%,也就是1-1/3-1/3=1/3。所以三条规则的权重是一样的,和设置的1,1,1是一样的比例。
第四步:
Chain FW1MARK (References: 3)
Rule # Pkts. Traffic Target Prot. Flags In Out Source Destination Options
1 7326 541.71 KB MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x10
2 7326 541.71 KB CONNMARK all -- * * 0.0.0.0/0 0.0.0.0/0 CONNMARK save
第五步:
root@lab-bashful:~# ip rule
0: from all lookup local
9: from all fwmark 0x1 lookup LoadBalancer
10: from 10.1.0.100 lookup MWAN1
11: from all fwmark 0x10 lookup MWAN1
20: from 10.1.1.100 lookup MWAN2
21: from all fwmark 0x20 lookup MWAN2
30: from 10.1.2.100 lookup MWAN3
31: from all fwmark 0x30 lookup MWAN3
32766: from all lookup main
32767: from all lookup default
第六步:
root@lab-bashful:~# ip route show table MWAN1
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2
10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.100
10.1.1.0/24 dev eth2 proto kernel scope link src 10.1.1.100
10.1.2.0/24 dev eth3 proto kernel scope link src 10.1.2.100
default via 10.1.0.2 dev eth1 proto static src 10.1.0.100
这种实现方式的好处就是,对于同一个目标IP,不同连接也有可能走不同的WAN,带宽叠加效果更好。用Compatibility模式的Balancer 的时候,不禁用路由缓存的话,每次traceroute的结果都是一样。但是使用了Fast模式的Balancer,即便有路由缓 存,traceroute也会发生变化,因为每次新建立的连接,第三步都会重新按概率派发到不同的下级规则。用aira2c测试四线程并发下载,也可以达 到最大带宽。所以Fast Balancer在这个设置下也可以叠加带宽,而且叠加效果似乎还不错,连同目标IP都能够叠加。
但是在openwrt的论坛上mwan2的作者说multiwan使用了太多的iptables规则。
Why should i use mwan2 instead of multi-wan ?:
- It is faster; mwan2 uses less iptables-rules.
- It is more configurable; mwan2 can handle multiple levels of backup interfaces, load-balanced or not.
- It is compatible; mwan2 uses flowmask to be compatible with other packages (such as OpenVPN, PPTP VPN, QoS-script, Tunnels, etc) and you can configure destinations to fall-back to the default routing table.
实验:使用multiwan叠加带宽(模式Compatibility Balancer,相同出口网关,相同目标服务器)
更新一下网络拓扑图:
在相同网关的情况下,traceroute已经无法得知走的是哪条路由了。每次的结果都是一样的(因为网关只有一个嘛)。但是在lab-bashful上查看路由缓存还是可以看出端倪来的
1 #从lab-doc发几个包到lab-sleepy 2 root@lab-bashful:~# ip route show cache | grep 10.2.0.100 3 10.0.0.100 from 10.2.0.100 dev eth0 src 10.1.0.100 4 10.2.0.100 from 10.0.0.100 via 10.1.0.2 dev eth3 src 10.0.0.2 5 root@lab-bashful:~# ip route flush cache 6 #从lab-doc发几个包到lab-sleepy 7 root@lab-bashful:~# ip route show cache | grep 10.2.0.100 8 10.2.0.100 from 10.0.0.100 via 10.1.0.2 dev eth1 src 10.0.0.2 9 10.0.0.100 from 10.2.0.100 dev eth0 src 10.1.0.100
可以看到有的时候走的是eth3,有的时候走的是eth0。那么实际的下载速度是不是能够叠加呢?
使用aria2c并发四线程下载,用内核参数禁用掉lab-bashfuld的路由缓存,下载速度可以达到19.8kb/s。
也就是说使用multiwan,兼容模式的balancer,相同网关是可以叠加的。
我之前的印象是,网关相同的话,multiwan无法叠加。
1 root@lab-bashful:~# ip route show table LoadBalancer 2 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2 3 10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.100 4 default proto static 5 nexthop via 10.1.0.2 dev eth1 weight 10 6 nexthop via 10.1.0.2 dev eth2 weight 10 7 nexthop via 10.1.0.2 dev eth3 weight 10
难道是我记错了吗?实验一下Fast Balancer看看
实验:使用multiwan叠加带宽(模式Fast Balancer,相同出口网关,相同目标服务器)
1 root@lab-bashful:~# ip route show table MWAN1 2 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2 3 10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.100 4 default via 10.1.0.2 dev eth1 proto static src 10.1.0.100 5 root@lab-bashful:~# ip route show table MWAN2 6 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2 7 10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.100 8 default via 10.1.0.2 dev eth1 proto static src 10.1.0.101 9 root@lab-bashful:~# ip route show table MWAN3 10 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2 11 10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.100 12 default via 10.1.0.2 dev eth1 proto static src 10.1.0.102
啊偶,Fast Balancer确实对于相同网关有BUG,三个路由表(MWAN1,MWAN2,MWAN3)都是相同的出口(IP相同,设备相同)。
用多线程下载实测,确实没有叠加!手工修改MWAN2和MWAN3之后,恢复正常。
【小结】
自此,本实验第一部分告一段落。本次实验包括了multiwan的测试,接下来会有后续实验测试m-route,nwan和mwan2的行为。
1、不同网关,Compatibility => 原理是ip route nexthop,叠加成功(相同目标IP,需要禁用路由缓存)
2、不同网关,Fast => 原理是iptables, mark, 特定routing table, default route,叠加成功(相同IP无需禁用路由缓存)
3、相同网关,Compatibility => 同1
4、相同网关,Fast => 叠加失败,每个mark的routing table都被设置成为了相同的出口
【转自】http://www.openwrt.org.cn/bbs/thread-9848-1-1.html
【相关资料】
http://www.hangge.com/blog/cache/detail_601.html