經常在論壇上看到對多撥之后帶寬無法疊加的抱怨。經過一段時間的研究,發現目前主流有三種工具來幫助我們實現多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