前题
- 硬件:路由器,刷入OpenWrt
- 一些背景知识和动手能力
目标效果图
步骤
- 使用SSH 登陆路由器。I.e. ssh [email protected]
- 运行/usr/bin/duobo。日志类似:
sh: : 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 ''
* Rule ''
* Rule ''
* Rule ''
* 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次拔号...........
正在并发拔号中.............
等待3秒.............
[]拔[]拔成功, 小于设定的[]拔,将重新拔号... _________________________- 如果没有成功并发多播,根据提示信息调整duobo的内部参数设置,重新运行。分享一些技巧:
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
遗留问题
开始第3次拔号...........
正在并发拔号中.............
等待10秒.............
pppoe-wan Link encap:Point-to-Point Protocol
pppoe-wan3 Link encap:Point-to-Point Protocol
[]拔[]拔成功, 大于或等于设定的[]拨,退出拔号...
Error: an inet address is expected rather than "dev".
iptables v1.4.10: Couldn't load target `zone_wan_notrack':File not found Try `iptables -h' or 'iptables --help' for more information.
iptables v1.4.10: Couldn't load target `zone_wan_nat':File not found Try `iptables -h' or 'iptables --help' for more information.
iptables: No chain/target/match by that name.
iptables v1.4.10: Couldn't load target `zone_wan':File not found Try `iptables -h' or 'iptables --help' for more information.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
Error: an inet address is expected rather than "dev".
iptables v1.4.10: Couldn't load target `zone_wan_notrack':File not found Try `iptables -h' or 'iptables --help' for more information.
iptables v1.4.10: Couldn't load target `zone_wan_nat':File not found Try `iptables -h' or 'iptables --help' for more information.
iptables: No chain/target/match by that name.
iptables v1.4.10: Couldn't load target `zone_wan':File not found Try `iptables -h' or 'iptables --help' for more information.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
iptables: No chain/target/match by that name.
Error: an IP address is expected rather than "dev"
192.168.2.0/ dev br-lan proto kernel scope link src 192.168.2.1
221.218.232.1 dev pppoe-wan3 proto kernel scope link src 123.112.248.148
221.218.232.1 dev pppoe-wan proto kernel scope link src 221.218.236.51
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.2.0 0.0.0.0 255.255.255.0 U br-lan
221.218.232.1 0.0.0.0 255.255.255.255 UH pppoe-wan3
221.218.232.1 0.0.0.0 255.255.255.255 UH pppoe-wan
View Error Code
显然这个0.3版本的脚本不完全适用于我的路由器,有时间我需要查查原因。
估计都是关于iptables
有没有大侠探讨一下?
修正了下面版本中的一个错误
line 19:if [ $j -ge $ok ] ;
多拨代码(V0.3)
#!/bin/sh
#modified by muziling v0.
#并发多拨脚本 #number是重拔次数
#n是几拔
#ok是拔上几次后退出拔号
#wait time number=
n=
ok=
wait=
# avoid same with feixiang's N-WAN naming and must start with "wan"
prefix=wan
vthprefix=vth j=$(ifconfig | grep pppoe-wan | wc -l)
if [ "$j" >= "$ok" ] ;
then
echo 已经是[$j]拔了,退出拔号...
exit
fi if [ -f /etc/config/nwannumset ] ;
then
uci set nwannumset.@macvlan_numset[].macvlan_num=
uci commit nwannumset
fi
for i in $( seq $(($n-)))
do
ifname=$prefix$i
ifvth=$vthprefix$i
#ifwan=$(uci get network.wan.ifname)
pppoe_name=$(uci get network.wan.username)
pppoe_pw=$(uci get network.wan.password) if [ $(ip link | grep " ${ifvth}@eth0.2:" | wc -l) == "" ] ;
then
macfac=$(ifconfig | grep eth0. | tr -s " " | cut -d " " -f5 | cut -b -)
mac="$macfac:"$(md5sum /proc/sys/kernel/random/uuid | sed 's/\(..\)/&:/g' | cut -b - | tr [a-f] [A-F])
ip link add link eth0. $ifvth type macvlan
ifconfig $ifvth hw ether $mac
fi # add /etc/config/network
uci delete network.$ifname
uci set network.$ifname=interface
uci set network.$ifname.ifname=$ifvth
#uci set network.$ifname._orig_ifname=eth0.
#uci set network.$ifname._orig_bridge=false
uci set network.$ifname.proto=pppoe
uci set network.$ifname.username=$pppoe_name
uci set network.$ifname.password=$pppoe_pw
uci set network.$ifname.auto=
uci set network.$ifname.defaultroute=
uci set network.$ifname.peerdns=
uci set network.$ifname.pppd_options="plugin rp-pppoe.so syncppp $n" # add /etc/config/dhcp
uci delete dhcp.$ifvth
uci set dhcp.$ifvth=dhcp
uci set dhcp.$ifvth.interface=$ifname
uci set dhcp.$ifvth.ignore= if [ -f /etc/config/nwan ] ;
then
uci delete nwan.$ifname
uci set nwan.$ifname=interface
uci set nwan.$ifname.name=telecom
uci set nwan.$ifname.route=balance
uci set nwan.$ifname.weight=
uci set nwan.$ifname.uptime=0day,0hour,0min
uci commit nwan
fi
done
uci set network.wan.defaultroute=
uci set network.wan.peerdns=
uci set network.wan.pppd_options="plugin rp-pppoe.so syncppp $n"
uci commit network
uci commit dhcp fw_wan_list=$(uci show network |grep =interface |grep -v lan|grep -v loopback |cut -d"." -f2 | awk -F "=" '{printf $1" "}')
uci set firewall.@zone[].network="$fw_wan_list"
uci commit firewall
/etc/init.d/firewall restart for q in $( seq $number )
do
echo
echo ___________________________________________________
echo 开始第$q次拔号...........
killall -q -SIG pppd
if [ "$q" == "" ] ;
then
for i in $( seq $(($n-)))
do
ifup $prefix$i
done
fi echo 正在并发拔号中.............
echo 等待$wait秒.............
sleep $wait j=$(ps | grep pppd | wc -l)
! [ "$j" -ge "$n" ] && ifup ${prefix} ifconfig|grep pppoe
j=$(ifconfig | grep pppoe-wan | wc -l) ! [ "$j" -ge "$ok" ] && echo [$n]拔[$j]拔成功, 小于设定的[$ok]拔,将重新拔号...
[ "$j" -ge "$ok" ] && echo [$n]拔[$j]拔成功, 大于或等于设定的[$ok]拨,退出拔号... if [ "$j" -ge "$ok" ] ;
then
for i in $( seq $(($n-)))
do
if [ "$i" == "" ] ;
then
interface=wan
else
interface=$prefix$i
fi
if [ $(ifconfig | grep "pppoe-$interface " | wc -l) == "" ] ;
then
ifdown $interface
fi
done
break
fi
done
# kill ddns sleep and re-check wan ip change
killall sleep j=$(ifconfig | grep pppoe-wan | wc -l)
! [ "$j" -ge ] && reboot #ppoename=$(ifconfig |grep 'ppoe-' |awk '{print substr($1,7)}'|tr '\n' ' ')
ppoename=$(ifconfig |grep 'ppoe-' |awk '{print $1}'|tr '\n' ' ')
i=
vias=""
for wan_ifname in $ppoename
do
vias="$vias nexthop via $wan_ip dev $wan_ifname weight 1 "
let "rt=100+$i"
i=$(($i+))
ip route flush table $rt
ip route add default via $wan_ip dev $wan_ifname table $rt
ip route add table $rt to $(ip route | grep br-lan) if [ $(iptables -t nat -vxnL POSTROUTING | grep -c " $wan_ifname ") == "" ] ;
then
iptables -t raw -A PREROUTING -i $wan_ifname -j zone_wan_notrack
iptables -t nat -A PREROUTING -i $wan_ifname -j zone_wan_prerouting
iptables -t nat -A POSTROUTING -o $wan_ifname -j zone_wan_nat
iptables -t filter -A forward -i $wan_ifname -j zone_wan_forward
iptables -t filter -A input -i $wan_ifname -j zone_wan
iptables -t filter -A zone_wan_ACCEPT -o $wan_ifname -j ACCEPT
iptables -t filter -A zone_wan_ACCEPT -i $wan_ifname -j ACCEPT
iptables -t filter -A zone_wan_DROP -o $wan_ifname -j DROP
iptables -t filter -A zone_wan_DROP -i $wan_ifname -j DROP
iptables -t filter -A zone_wan_REJECT -o $wan_ifname -j reject
iptables -t filter -A zone_wan_REJECT -i $wan_ifname -j reject
fi
iptables -A PREROUTING -t mangle -i $wan_ifname -j MARK --set-mark $rt
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
ip rule add fwmark $rt table $rt prio $rt
done
ip route del default
ip route add default scope global $vias
ip route flush cache
ip route list
route -n
root@OpenWrt:~#
(duobo)
修订版(V0.3.1)
#!/bin/sh
#modified by muziling v0.
#并发多拨脚本
#modified by carl v0.3.1 (修正一处bug,改善友好提示信息) #number是重拔次数,本脚本启动后一共尝试的次数
#n是几拔,同时发出几拨,理论上设置越大成功概率越大!
#ok是拔上几次后退出拔号, 要实现的预期目标
#wait time 每次单线多拨失败后,重试的等待时间 number=
n=
ok=
wait=
# avoid same with feixiang's N-WAN naming and must start with "wan"
prefix=wan
vthprefix=vth j=$(ifconfig | grep pppoe-wan | wc -l)
if [ $j -ge $ok ] ;
then
echo 已经是[$j]拔了,退出拔号程序。
exit
fi if [ -f /etc/config/nwannumset ] ;
then
uci set nwannumset.@macvlan_numset[].macvlan_num=
uci commit nwannumset
fi for i in $( seq $(($n-)))
do
ifname=$prefix$i
ifvth=$vthprefix$i
#ifwan=$(uci get network.wan.ifname)
pppoe_name=$(uci get network.wan.username)
pppoe_pw=$(uci get network.wan.password) if [ $(ip link | grep " ${ifvth}@eth0.2:" | wc -l) == "" ] ;
then
macfac=$(ifconfig | grep eth0. | tr -s " " | cut -d " " -f5 | cut -b -)
mac="$macfac:"$(md5sum /proc/sys/kernel/random/uuid | sed 's/\(..\)/&:/g' | cut -b - | tr [a-f] [A-F])
ip link add link eth0. $ifvth type macvlan
ifconfig $ifvth hw ether $mac
echo 更换MAC完毕$ifvth.
fi # add /etc/config/network
uci delete network.$ifname
uci set network.$ifname=interface
uci set network.$ifname.ifname=$ifvth
#uci set network.$ifname._orig_ifname=eth0.
#uci set network.$ifname._orig_bridge=false
uci set network.$ifname.proto=pppoe
uci set network.$ifname.username=$pppoe_name
uci set network.$ifname.password=$pppoe_pw
uci set network.$ifname.auto=
uci set network.$ifname.defaultroute=
uci set network.$ifname.peerdns=
uci set network.$ifname.pppd_options="plugin rp-pppoe.so syncppp $n" # add /etc/config/dhcp
uci delete dhcp.$ifvth
uci set dhcp.$ifvth=dhcp
uci set dhcp.$ifvth.interface=$ifname
uci set dhcp.$ifvth.ignore= if [ -f /etc/config/nwan ] ;
then
uci delete nwan.$ifname
uci set nwan.$ifname=interface
uci set nwan.$ifname.name=unicom
uci set nwan.$ifname.route=balance
uci set nwan.$ifname.weight=
uci set nwan.$ifname.uptime=0day,0hour,0min
uci commit nwan
fi
done uci set network.wan.defaultroute=
uci set network.wan.peerdns=
uci set network.wan.pppd_options="plugin rp-pppoe.so syncppp $n"
uci commit network
uci commit dhcp fw_wan_list=$(uci show network |grep =interface |grep -v lan|grep -v loopback |cut -d"." -f2 | awk -F "=" '{printf $1" "}')
uci set firewall.@zone[].network="$fw_wan_list"
uci commit firewall
/etc/init.d/firewall restart for q in $( seq $number )
do
echo
echo ___________________________________________________
echo 开始第$q次拔号...........
killall -q -SIG pppd
if [ "$q" == "" ] ;
then
for i in $( seq $(($n-)))
do
ifup $prefix$i
done
fi echo 正在并发拔号中.............
echo 等待$wait秒.............
sleep $wait j=$(ps | grep pppd | wc -l)
! [ "$j" -ge "$n" ] && ifup ${prefix} ifconfig | grep pppoe
j=$(ifconfig | grep pppoe-wan | wc -l) ! [ "$j" -ge "$ok" ] && echo [$n]拔[$j]拔成功, 小于设定的[$ok]拔,将重新拔号...
[ "$j" -ge "$ok" ] && echo [$n]拔[$j]拔成功, 大于或等于设定的[$ok]拨,退出拔号... if [ "$j" -ge "$ok" ] ;
then
for i in $( seq $(($n-)))
do
if [ "$i" == "" ] ;
then
interface=wan
else
interface=$prefix$i
fi
if [ $(ifconfig | grep "pppoe-$interface " | wc -l) == "" ] ;
then
ifdown $interface
fi
done
break
fi
done # done/tried all tring times $number # kill ddns sleep and re-check wan ip change
killall sleep # reboot the machine if failed tried times
#sleep $wait
j=$(ifconfig | grep pppoe-wan | wc -l)
! [ "$j" -gt ] && reboot echo ___________________________________________________
echo 开始N-WAN负载均衡功能...
#ppoename=$(ifconfig |grep 'ppoe-' |awk '{print substr($1,7)}'|tr '\n' ' ')
ppoename=$(ifconfig|grep 'ppoe-' |awk '{print $1}'|tr '\n' ' ')
i=
vias=""
for wan_ifname in $ppoename
do
vias="$vias nexthop via $wan_ip dev $wan_ifname weight 1 "
let "rt=100+$i"
i=$(($i+))
ip route flush table $rt
#REMOVE ERROR
ip route add default via $wan_ip dev $wan_ifname table $rt
ip route add table $rt to $(ip route | grep br-lan) if [ $(iptables -t nat -vxnL POSTROUTING | grep -c " $wan_ifname ") == "" ] ;
then
#REMOVE ERROR
iptables -t raw -A PREROUTING -i $wan_ifname -j zone_wan_notrack
iptables -t nat -A PREROUTING -i $wan_ifname -j zone_wan_prerouting
#REMOVE ERROR
iptables -t nat -A POSTROUTING -o $wan_ifname -j zone_wan_nat
iptables -t filter -A forward -i $wan_ifname -j zone_wan_forward
#REMOVE ERROR
iptables -t filter -A input -i $wan_ifname -j zone_wan
iptables -t filter -A zone_wan_ACCEPT -o $wan_ifname -j ACCEPT
iptables -t filter -A zone_wan_ACCEPT -i $wan_ifname -j ACCEPT
iptables -t filter -A zone_wan_DROP -o $wan_ifname -j DROP
iptables -t filter -A zone_wan_DROP -i $wan_ifname -j DROP
iptables -t filter -A zone_wan_REJECT -o $wan_ifname -j reject
iptables -t filter -A zone_wan_REJECT -i $wan_ifname -j reject
fi iptables -A PREROUTING -t mangle -i $wan_ifname -j MARK --set-mark $rt
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
ip rule add fwmark $rt table $rt prio $rt
done ip route del default echo ___________________________________________________
echo 下面执行ip route add default scope global $vias
ip route add default scope global $vias ip route flush cache echo ___________________________________________________
echo 下面输出ip route list
ip route list echo ___________________________________________________
echo 下面输出route -n
route -n
参考文献
OpenWrt For AR71xx系列 ar2 Tr 脱机 N-WAN r48549