OpenWrt > ADSL单线多拨,负载均衡(仅供参考)

时间:2024-03-11 21:20:37
  • 2021年11月更新:如果是K2P A2版本硬件,请参考更简易的步骤,更加高效,不需要太多代码知识。 K2P刷机-坐标北京Unicom

前题


  • 硬件:路由器,刷入OpenWrt
  • 一些背景知识和动手能力

目标效果图


 

实际例子Sample

步骤


  1. 使用SSH 登陆路由器。I.e. ssh root@192.168.2.1
  2. 运行/usr/bin/duobo。日志类似:
  3. sh: 2: unknown operand
    Killed
    Warning: Unable to locate ipset utility, disabling ipset support
     * Flushing IPv4 filter table
     * Flushing IPv4 nat table
     * Flushing IPv4 mangle table
     * Flushing IPv4 raw table
     * Flushing conntrack table ...
     * Populating IPv4 filter table
       * Zone \'lan\'
       * Zone \'wan\'
       * Rule \'Allow-DHCP-Renew\'
       * Rule \'Allow-Ping\'
       * Rule \'51413\'
       * Rule \'9091\'
       * Rule \'9000\'
       * Rule \'6800\'
       * Forward \'lan\' -> \'wan\'
     * Populating IPv4 nat table
       * Zone \'lan\'
       * Zone \'wan\'
     * Populating IPv4 mangle table
       * Zone \'lan\'
       * Zone \'wan\'
     * Populating IPv4 raw table
       * Zone \'lan\'
       * Zone \'wan\'
     * Set tcp_ecn to off
     * Set tcp_syncookies to on
     * Set tcp_window_scaling to on
     * Running script \'/etc/firewall.user\'
     * Running script \'/usr/share/miniupnpd/firewall.include\'
     * Running script \'/usr/share/qos_gargoyle/firewall.include\'
       ! Failed with exit code 1
    
    ___________________________________________________
    开始第1次拔号...........
    正在并发拔号中.............
    等待3秒.............
    [3]拔[0]拔成功, 小于设定的[2]拔,将重新拔号...
    
    _________________________
    View Code
  4. 如果没有成功并发多播,根据提示信息调整duobo的内部参数设置,重新运行。分享一些技巧:
  5. number=10 #number是重拔次数,本脚本启动后一共尝试的次数
    n=7 #n是几拔,同时发出几拨,理论上设置越大成功概率越大!
    ok=2 #ok是拔上几次后退出拔号, 要实现的预期目标
    wait=5 #wait time 每次单线多拨失败后,重试的等待时间
    • 原则:失败多次以后,建议冷重启路由器,多个运行中的脚本会互相冲突,把问题复杂化。
    • 多拨失败以后,耐心等上1分钟;很多次的多播成功都是脚本完成以后退出,然后60秒内获取了超过预期的多条链接。
    • 把n调到7,这样会虚拟出很多wan接口,根据硬件性能,理论上设置越大成功概率越大!
    • 将ok调低一点,比如2。我觉得别太贪心,如果能稳定多播2个ADSL的IP,那其实概率上更折中了稳定性和高负载下的带宽均衡。
    • wait的时间我感觉5秒-8秒差不多,这个要看运行日志,做相应调整。
    • 看懂程序的原理,根据实际情况调整脚本程序。比如:这个版本的程序是这么多播的,ifup $prefix$i

遗留问题


 

 1 开始第3次拔号...........
 2 正在并发拔号中.............
 3 等待10秒.............
 4 pppoe-wan Link encap:Point-to-Point Protocol  
 5 pppoe-wan3 Link encap:Point-to-Point Protocol  
 6 [3]拔[2]拔成功, 大于或等于设定的[2]拨,退出拔号...
 7 Error: an inet address is expected rather than "dev".
 8 iptables v1.4.10: Couldn\'t load target `zone_wan_notrack\':File not found
 9 
10 Try `iptables -h\' or \'iptables --help\' for more information.
11 iptables v1.4.10: Couldn\'t load target `zone_wan_nat\':File not found
12 
13 Try `iptables -h\' or \'iptables --help\' for more information.
14 iptables: No chain/target/match by that name.
15 iptables v1.4.10: Couldn\'t load target `zone_wan\':File not found
16 
17 Try `iptables -h\' or \'iptables --help\' for more information.
18 iptables: No chain/target/match by that name.
19 iptables: No chain/target/match by that name.
20 iptables: No chain/target/match by that name.
21 iptables: No chain/target/match by that name.
22 iptables: No chain/target/match by that name.
23 iptables: No chain/target/match by that name.
24 iptables: No chain/target/match by that name.
25 Error: an inet address is expected rather than "dev".
26 iptables v1.4.10: Couldn\'t load target `zone_wan_notrack\':File not found
27 
28 Try `iptables -h\' or \'iptables --help\' for more information.
29 iptables v1.4.10: Couldn\'t load target `zone_wan_nat\':File not found
30 
31 Try `iptables -h\' or \'iptables --help\' for more information.
32 iptables: No chain/target/match by that name.
33 iptables v1.4.10: Couldn\'t load target `zone_wan\':File not found
34 
35 Try `iptables -h\' or \'iptables --help\' for more information.
36 iptables: No chain/target/match by that name.
37 iptables: No chain/target/match by that name.
38 iptables: No chain/target/match by that name.
39 iptables: No chain/target/match by that name.
40 iptables: No chain/target/match by that name.
41 iptables: No chain/target/match by that name.
42 iptables: No chain/target/match by that name.
43 Error: an IP address is expected rather than "dev"
44 192.168.2.0/24 dev br-lan  proto kernel  scope link  src 192.168.2.1 
45 221.218.232.1 dev pppoe-wan3  proto kernel  scope link  src 123.112.248.148 
46 221.218.232.1 dev pppoe-wan  proto kernel  scope link  src 221.218.236.51 
47 Kernel IP routing table
48 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
49 192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 br-lan
50 221.218.232.1   0.0.0.0         255.255.255.255 UH    0      0        0 pppoe-wan3
51 221.218.232.1   0.0.0.0         255.255.255.255 UH    0      0        0 pppoe-wan
View Error Code

显然这个0.3版本的脚本不完全适用于我的路由器,有时间我需要查查原因。

估计都是关于iptables

有没有大侠探讨一下?

修正了下面版本中的一个错误

line 19:if [ $j -ge $ok ] ;

 

多拨代码(V0.3)


 

  1 #!/bin/sh
  2 #modified by muziling v0.3
  3 #并发多拨脚本
  4 
  5 #number是重拔次数
  6 #n是几拔
  7 #ok是拔上几次后退出拔号
  8 #wait time
  9 
 10 number=10
 11 n=3
 12 ok=2
 13 wait=5
 14 # avoid same with feixiang\'s N-WAN naming and must start with "wan"
 15 prefix=wan
 16 vthprefix=vth
 17 
 18 j=$(ifconfig | grep pppoe-wan | wc -l)
 19 if [ "$j" >= "$ok" ] ;
 20 then
 21     echo 已经是[$j]拔了,退出拔号...
 22     exit 0
 23 fi
 24 
 25 if [ -f /etc/config/nwannumset ] ;
 26 then
 27     uci set nwannumset.@macvlan_numset[0].macvlan_num=1
 28     uci commit nwannumset
 29 fi
 30 for i in $( seq 1 $(($n-1)))
 31 do
 32     ifname=$prefix$i
 33     ifvth=$vthprefix$i
 34     #ifwan=$(uci get network.wan.ifname)
 35     pppoe_name=$(uci get network.wan.username) 
 36     pppoe_pw=$(uci get network.wan.password) 
 37 
 38     if [ $(ip link | grep " ${ifvth}@eth0.2:" | wc -l) == "0" ] ;
 39     then
 40         macfac=$(ifconfig | grep eth0.2 | tr -s " " | cut -d " " -f5 | cut -b 1-8)
 41         mac="$macfac:"$(md5sum /proc/sys/kernel/random/uuid | sed \'s/\(..\)/&:/g\' | cut -b 1-8 | tr [a-f] [A-F])
 42         ip link add link eth0.2 $ifvth type macvlan
 43         ifconfig $ifvth hw ether $mac
 44     fi
 45 
 46     # add /etc/config/network
 47     uci delete network.$ifname
 48     uci set network.$ifname=interface
 49     uci set network.$ifname.ifname=$ifvth
 50     #uci set network.$ifname._orig_ifname=eth0.2
 51     #uci set network.$ifname._orig_bridge=false
 52     uci set network.$ifname.proto=pppoe
 53     uci set network.$ifname.username=$pppoe_name
 54     uci set network.$ifname.password=$pppoe_pw
 55     uci set network.$ifname.auto=0
 56     uci set network.$ifname.defaultroute=0
 57     uci set network.$ifname.peerdns=1
 58     uci set network.$ifname.pppd_options="plugin rp-pppoe.so syncppp $n"
 59 
 60     # add /etc/config/dhcp
 61     uci delete dhcp.$ifvth
 62     uci set dhcp.$ifvth=dhcp 
 63     uci set dhcp.$ifvth.interface=$ifname
 64     uci set dhcp.$ifvth.ignore=1 
 65 
 66     if [ -f /etc/config/nwan ] ;
 67     then
 68         uci delete nwan.$ifname
 69         uci set nwan.$ifname=interface 
 70         uci set nwan.$ifname.name=telecom 
 71         uci set nwan.$ifname.route=balance 
 72         uci set nwan.$ifname.weight=1 
 73         uci set nwan.$ifname.uptime=0day,0hour,0min
 74         uci commit nwan
 75     fi
 76 done
 77 uci set network.wan.defaultroute=0
 78 uci set network.wan.peerdns=1
 79 uci set network.wan.pppd_options="plugin rp-pppoe.so syncppp $n"
 80 uci commit network
 81 uci commit dhcp
 82 
 83 fw_wan_list=$(uci show network |grep =interface |grep -v lan|grep -v loopback |cut -d"." -f2 | awk -F "=" \'{printf $1" "}\')
 84 uci set firewall.@zone[1].network="$fw_wan_list"
 85 uci commit firewall
 86 /etc/init.d/firewall restart
 87 
 88 for q in $( seq 1 $number )
 89 do
 90     echo
 91     echo ___________________________________________________
 92     echo 开始第$q次拔号...........
 93     killall -q -SIG pppd
 94     if [ "$q" == "1" ] ;
 95     then
 96         for i in $( seq 1 $(($n-1)))
 97         do
 98             ifup $prefix$i
 99         done
100     fi
101 
102     echo 正在并发拔号中.............
103     echo 等待$wait秒.............
104     sleep $wait
105 
106     j=$(ps | grep pppd | wc -l)
107     ! [ "$j" -ge "$n" ]  && ifup ${prefix}1
108 
109     ifconfig|grep pppoe
110     j=$(ifconfig | grep pppoe-wan | wc -l)
111 
112     ! [ "$j" -ge "$ok" ] && echo [$n]拔[$j]拔成功, 小于设定的[$ok]拔,将重新拔号...
113     [ "$j" -ge "$ok" ] && echo [$n]拔[$j]拔成功, 大于或等于设定的[$ok]拨,退出拔号...
114 
115     if [ "$j" -ge "$ok" ] ;
116     then
117         for i in $( seq 0 $(($n-1)))
118         do
119             if [ "$i" == "0" ] ;
120             then
121                 interface=wan
122             else
123                 interface=$prefix$i
124             fi
125             if [ $(ifconfig | grep "pppoe-$interface " | wc -l) == "0" ] ;
126             then
127                 ifdown $interface
128             fi
129         done
130         break
131     fi
132 done
133 # kill ddns sleep and re-check wan ip change
134 killall sleep
135 
136 j=$(ifconfig | grep pppoe-wan | wc -l)
137 ! [ "$j" -ge 0 ] && reboot
138 
139 #ppoename=$(ifconfig |grep \'ppoe-\' |awk \'{print substr($1,7)}\'|tr \'\n\' \' \')
140 ppoename=$(ifconfig |grep \'ppoe-\' |awk \'{print $1}\'|tr \'\n\' \' \')
141 i=0
142 vias=""
143 for wan_ifname in $ppoename
144 do
145     vias="$vias nexthop via $wan_ip dev $wan_ifname weight 1 "
146     let "rt=100+$i"
147     i=$(($i+1))
148     ip route flush table $rt
149     ip route add default via $wan_ip dev $wan_ifname table $rt
150     ip route add table $rt to $(ip route | grep br-lan)
151 
152     if [ $(iptables -t nat -vxnL POSTROUTING | grep -c " $wan_ifname ") == "0" ] ;
153     then
154         iptables -t raw -A PREROUTING -i $wan_ifname -j zone_wan_notrack
155         iptables -t nat -A PREROUTING -i $wan_ifname -j zone_wan_prerouting
156         iptables -t nat -A POSTROUTING -o $wan_ifname -j zone_wan_nat
157         iptables -t filter -A forward -i $wan_ifname -j zone_wan_forward
158         iptables -t filter -A input -i $wan_ifname -j zone_wan
159         iptables -t filter -A zone_wan_ACCEPT -o $wan_ifname -j ACCEPT
160         iptables -t filter -A zone_wan_ACCEPT -i $wan_ifname -j ACCEPT
161         iptables -t filter -A zone_wan_DROP -o $wan_ifname -j DROP
162         iptables -t filter -A zone_wan_DROP -i $wan_ifname -j DROP
163         iptables -t filter -A zone_wan_REJECT -o $wan_ifname -j reject
164         iptables -t filter -A zone_wan_REJECT -i $wan_ifname -j reject
165     fi
166     iptables -A PREROUTING -t mangle -i $wan_ifname -j MARK --set-mark $rt
167     iptables -t mangle -A zone_wan_MSSFIX -o $wan_ifname -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
168     ip rule add fwmark $rt table $rt prio $rt
169 done
170 ip route del default
171 ip route add default scope global $vias
172 ip route flush cache
173 ip route list
174 route -n
175 root@OpenWrt:~# 
View Code (duobo)

 

修订版(V0.3.1)

  1 #!/bin/sh
  2 #modified by muziling v0.3
  3 #并发多拨脚本
  4 #modified by carl v0.3.1 (修正一处bug,改善友好提示信息)
  5 
  6 #number是重拔次数,本脚本启动后一共尝试的次数
  7 #n是几拔,同时发出几拨,理论上设置越大成功概率越大!
  8 #ok是拔上几次后退出拔号, 要实现的预期目标
  9 #wait time 每次单线多拨失败后,重试的等待时间
 10 
 11 number=15
 12 n=7
 13 ok=2
 14 wait=8
 15 # avoid same with feixiang\'s N-WAN naming and must start with "wan"
 16 prefix=wan
 17 vthprefix=vth
 18 
 19 j=$(ifconfig | grep pppoe-wan | wc -l)
 20 if [ $j -ge $ok ] ;
 21 then
 22     echo 已经是[$j]拔了,退出拔号程序。
 23     exit 0
 24 fi
 25 
 26 if [ -f /etc/config/nwannumset ] ;
 27 then
 28     uci set nwannumset.@macvlan_numset[0].macvlan_num=1
 29     uci commit nwannumset
 30 fi
 31 
 32 for i in $( seq 1 $(($n-1)))
 33 do
 34     ifname=$prefix$i
 35     ifvth=$vthprefix$i
 36     #ifwan=$(uci get network.wan.ifname)
 37     pppoe_name=$(uci get network.wan.username) 
 38     pppoe_pw=$(uci get network.wan.password) 
 39 
 40     if [ $(ip link | grep " ${ifvth}@eth0.2:" | wc -l) == "0" ] ;
 41     then
 42         macfac=$(ifconfig | grep eth0.2 | tr -s " " | cut -d " " -f5 | cut -b 1-8)
 43         mac="$macfac:"$(md5sum /proc/sys/kernel/random/uuid | sed \'s/\(..\)/&:/g\' | cut -b 1-8 | tr [a-f] [A-F])
 44         ip link add link eth0.2 $ifvth type macvlan
 45         ifconfig $ifvth hw ether $mac
 46         echo 更换MAC完毕$ifvth.
 47     fi
 48 
 49     # add /etc/config/network
 50     uci delete network.$ifname
 51     uci set network.$ifname=interface
 52     uci set network.$ifname.ifname=$ifvth
 53     #uci set network.$ifname._orig_ifname=eth0.2
 54     #uci set network.$ifname._orig_bridge=false
 55     uci set network.$ifname.proto=pppoe
 56     uci set network.$ifname.username=$pppoe_name
 57     uci set network.$ifname.password=$pppoe_pw
 58     uci set network.$ifname.auto=0
 59     uci set network.$ifname.defaultroute=0
 60     uci set network.$ifname.peerdns=1
 61     uci set network.$ifname.pppd_options="plugin rp-pppoe.so syncppp $n"
 62 
 63     # add /etc/config/dhcp
 64     uci delete dhcp.$ifvth
 65     uci set dhcp.$ifvth=dhcp 
 66     uci set dhcp.$ifvth.interface=$ifname
 67     uci set dhcp.$ifvth.ignore=1 
 68 
 69     if [ -f /etc/config/nwan ] ;
 70     then
 71         uci delete nwan.$ifname
 72         uci set nwan.$ifname=interface 
 73         uci set nwan.$ifname.name=unicom 
 74         uci set nwan.$ifname.route=balance 
 75         uci set nwan.$ifname.weight=1 
 76         uci set nwan.$ifname.uptime=0day,0hour,0min
 77         uci commit nwan
 78     fi
 79 done
 80 
 81 uci set network.wan.defaultroute=0
 82 uci set network.wan.peerdns=1
 83 uci set network.wan.pppd_options="plugin rp-pppoe.so syncppp $n"
 84 uci commit network
 85 uci commit dhcp
 86 
 87 fw_wan_list=$(uci show network |grep =interface |grep -v lan|grep -v loopback |cut -d"." -f2 | awk -F "=" \'{printf $1" "}\')
 88 uci set firewall.@zone[1].network="$fw_wan_list"
 89 uci commit firewall
 90 /etc/init.d/firewall restart
 91 
 92 for q in $( seq 1 $number )
 93 do
 94     echo
 95     echo ___________________________________________________
 96     echo 开始第$q次拔号...........
 97     killall -q -SIG pppd
 98     if [ "$q" == "1" ] ;
 99     then
100         for i in $( seq 1 $(($n-1)))
101         do
102             ifup $prefix$i
103         done
104     fi
105 
106     echo 正在并发拔号中.............
107     echo 等待$wait秒.............
108     sleep $wait
109 
110     j=$(ps | grep pppd | wc -l)
111     ! [ "$j" -ge "$n" ]  && ifup ${prefix}1
112 
113     ifconfig | grep pppoe
114     j=$(ifconfig | grep pppoe-wan | wc -l)
115 
116     ! [ "$j" -ge "$ok" ] && echo [$n]拔[$j]拔成功, 小于设定的[$ok]拔,将重新拔号...
117     [ "$j" -ge "$ok" ] && echo [$n]拔[$j]拔成功, 大于或等于设定的[$ok]拨,退出拔号...
118     
119     if [ "$j" -ge "$ok" ] ;
120     then
121         for i in $( seq 0 $(($n-1)))
122         do
123             if [ "$i" == "0" ] ;
124             then
125                 interface=wan
126             else
127                 interface=$prefix$i
128             fi
129             if [ $(ifconfig | grep "pppoe-$interface " | wc -l) == "0" ] ;
130             then
131                 ifdown $interface
132             fi
133         done
134         break
135     fi
136 done # done/tried all tring times $number
137 
138 # kill ddns sleep and re-check wan ip change
139 killall sleep
140 
141 # reboot the machine if failed tried times
142 #sleep $wait
143 j=$(ifconfig | grep pppoe-wan | wc -l)
144 ! [ "$j" -gt 0 ] && reboot
145 
146 
147 echo ___________________________________________________
148 echo 开始N-WAN负载均衡功能...
149 #ppoename=$(ifconfig |grep \'ppoe-\' |awk \'{print substr($1,7)}\'|tr \'\n\' \' \')
150 ppoename=$(ifconfig|grep \'ppoe-\' |awk \'{print $1}\'|tr \'\n\' \' \')
151 i=0
152 vias=""
153 for wan_ifname in $ppoename
154 do
155     vias="$vias nexthop via $wan_ip dev $wan_ifname weight 1 "
156     let "rt=100+$i"
157     i=$(($i+1))
158     ip route flush table $rt
159     #REMOVE ERROR
160     ip route add default via $wan_ip dev $wan_ifname table $rt
161     ip route add table $rt to $(ip route | grep br-lan)
162 
163     if [ $(iptables -t nat -vxnL POSTROUTING | grep -c " $wan_ifname ") == "0" ] ;
164     then
165         #REMOVE ERROR
166         iptables -t raw -A PREROUTING -i $wan_ifname -j zone_wan_notrack
167         iptables -t nat -A PREROUTING -i $wan_ifname -j zone_wan_prerouting
168         #REMOVE ERROR
169         iptables -t nat -A POSTROUTING -o $wan_ifname -j zone_wan_nat
170         iptables -t filter -A forward -i $wan_ifname -j zone_wan_forward
171         #REMOVE ERROR
172         iptables -t filter -A input -i $wan_ifname -j zone_wan
173         iptables -t filter -A zone_wan_ACCEPT -o $wan_ifname -j ACCEPT
174         iptables -t filter -A zone_wan_ACCEPT -i $wan_ifname -j ACCEPT
175         iptables -t filter -A zone_wan_DROP -o $wan_ifname -j DROP
176         iptables -t filter -A zone_wan_DROP -i $wan_ifname -j DROP
177         iptables -t filter -A zone_wan_REJECT -o $wan_ifname -j reject
178         iptables -t filter -A zone_wan_REJECT -i $wan_ifname -j reject
179     fi
180     
181     iptables -A PREROUTING -t mangle -i $wan_ifname -j MARK --set-mark $rt
182     iptables -t mangle -A zone_wan_MSSFIX -o $wan_ifname -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
183     ip rule add fwmark $rt table $rt prio $rt
184 done
185 
186 ip route del default
187 
188 echo ___________________________________________________
189 echo 下面执行ip route add default scope global $vias
190 ip route add default scope global $vias
191 
192 ip route flush cache
193 
194 echo ___________________________________________________
195 echo 下面输出ip route list
196 ip route list
197 
198 echo ___________________________________________________
199 echo 下面输出route -n
200 route -n
View Code

 

参考文献


 

OpenWrt For AR71xx系列 ar2 Tr 脱机 N-WAN r48549

自己动手 4530R 脱机 Samba U-BOOT 多拨(11-04更新部分问题说明,请看2楼)

[0916更新]WR703N WR720N 及其他各类 OpenWRT类路由实现一号多拨带宽叠加教程