1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

adding dualwan funtionality

Discussion in 'Tomato Firmware' started by rs232, Apr 27, 2011.

  1. rs232

    rs232 Network Guru Member

    adding dualwan funtionality!

    Hello,
    I read on this forum about the "missing" sources from the dualwan module. Shame!

    As I've been playing in these days with Zentyal and pfsense. As they do provide multiple gateway failover+load-sharing I was wondering if we can grab that piece of code from them. Zentyal in particular seems to be open-source ;-)

    e.g.
    http://doc.zentyal.org/en/routing.html#configuring-traffic-balancing-with-zentyal
     
  2. rs232

    rs232 Network Guru Member

  3. rs232

    rs232 Network Guru Member

    Actually... it works! :biggrin:

    I'm still tweaking things but I've successfully load-shared sessions between Internet gateways even using different weight just modifying the routing tables.
    I've been testing 2 gateways but once the core structure is defined there's no limit really.

    There's more to do though, the most important things are:

    DONE --> 1) automate some inputs (currently manual in my script) like:

    DONE --> - ISP network address (not the gateway IP, the network! e.g. 2.2.2.0) I've found a ksh93 script that given IP and subnet returns network address. I can't make it working using /bin/sh yet though. Any help? See fpmurphy post here: http://www.unix.com/shell-programmi...dress-netmask-using-bitwise-shell-script.html

    DONE --> - Add a conversion table from mask to prefix e.g. 255.255.254.0 = 23

    2) Patch the kernel to allow for gateway testing (see my previous post), to test the gateways every X seconds and remove them if success rate is not satisfied (e.g. 60% pings)

    3) -optional- route selected traffic always via selected gateway (no load balancing)

    4) Compile a gui for the configuration. Mod developers help?
    In particular there's a need to:

    - Define gateways and weight via GUI

    - Define gateways probes and frequency via GUI

    5) Testing



    If you want to give it a go run this on the shell of your router. I'm using the latest Victek on Asus RT-N16

    My scenario is:
    2x tomato connected via LAN
    tomato1 connected to my ISP via wan interface
    tomato2 connected to Internet as wireless client (to my neighbour :tongue:)

    Code:
    ## Assumptions:
    ## IF1 = router wan interface
    ## IF2 = router interface to secindary gateway, LAN in my case
    ## IP1 = router local WAN IP
    ## IP2 = router local LAN IP
    ## P1 = router remote WAN IP -> ISP IP (gateway) 
    ## P2 = router remote LAN IP --> a secon tomato connected ot the LAN in my case
    ## P1_NET = WAN net address + prefix (note netmask doesn't seem to be working so you'll need to use a prefix!)
    ## P2_NET = LAN net address + prefix (note netmask doesn't seem to be working so you'll need to use a prefix!)
    ##
    ##
    
    IF1=`nvram get wan_iface`  ## vlan 2 in my case you needn't touch this
    IF2=`nvram get lan_ifname` ## br0 in my case, you needn't touch this
    IP1=`nvram get wan_ipaddr` ## no need to touch this 
    IP2=`nvram get lan_ipaddr` ## you shouldn't need to change this but just in case...
    P1=`nvram get wan_gateway` ## no need to touch this 
    P2=10.10.10.2              ## manually set! 
    P1_NET=82.9.21.0/23        ## this for me is the wan_gateway -1 --> manually set for the time being
    P2_NET=10.10.10.0/24       ## this is the network connecting to the secondary gateway, in my case is the LAN. --> manually set
    W1=1 #Weight of gateway 1  ## 50% connection to Internet connection 1
    W2=1 #Weight of gateway 2  ## 50% connection to Internet connection 2
    
    ## Clear previous settings
    ip route flush table 1
    ip route flush table 2
    ip route del default
    ## Add main routing table to table 1
    ## ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table 1 $ROUTE ; done
    
    ip route add $P1_NET dev $IF1 src $IP1 table 1
    ip route add default via $P1 table 1
    ip route add $P2_NET dev $IF2 src $IP2 table 2
    ip route add default via $P2 table 2
    
    ## conversion between wan_netmask and prefix to be done! e.g. 255.255.255.0 = 24
    
    ip route del $P1_NET dev $IF1 src $IP1
    ip route add $P1_NET dev $IF1 src $IP1  ## Route each wan network out of the right internafe
    ip route del $P2_NET dev $IF2 src $IP2
    ip route add $P2_NET dev $IF2 src $IP2  ##
    
    ip rule add from $IP1 table 1
    ip rule add from $IP2 table 2
    
    ## Fianlly add the default route with 2 destinations and their own metrics
    ip route add default scope global nexthop via $P1 dev $IF1 weight $W1 nexthop via $P2 dev $IF2 weight $W2
    
    To verify:

    Code:
    ip route show table 1
    ## You should see the Internet connection 1 network and default gateway here
    
    ip route show table 2
    ## You should see the Internet connection 2 network and default gateway here
    
    ip route show table main
    ## You should see all your routes plus two next hop to the default gateway going to the IP/Interfaces defined above
    traceroute some random internet domains from one of your LAN clients to verify. NOTE: due to arp caching do test different domains, the result is "almost" round-robin. Same domain appears to stick to the same gateway until arp times out.

    Enjoy
    rs232
     
  4. TexasFlood

    TexasFlood Network Guru Member

    Pretty cool, :cool: Wish I had dual WANs, :frown:
     
  5. rs232

    rs232 Network Guru Member

    Point 1 is now completed:

    Code:
    ### Functions ###############################################
    
    getnetwork() {
    
    if [ "$2" ]; then
       NM="$2"
    else
       NM="255.255.255.0"
    fi
    if [ "$1" ]; then
       IP="$1"
    else
       IP="255.255.255.255"
    fi
    #
    n="${NM%.*}";m="${NM##*.}"
    l="${IP%.*}";r="${IP##*.}";c=""
    if [ "$m" = "0" ]; then
       c=".0"
       m="${n##*.}";n="${n%.*}"
       r="${l##*.}";l="${l%.*}"
       if [ "$m" = "0" ]; then
          c=".0$c"
          m="${n##*.}";n="${n%.*}"
          r="${l##*.}";l="${l%.*}"
          if [ "$m" = "0" ]; then
             c=".0$c"
             m=$n
             r=$l;l=""
          fi
       fi
    fi
    let s=256-$m
    let r=$r/$s*$s
    if [ "$l" ]; then
       SNW="$l.$r$c"
    else
       SNW="$r$c"
    fi
    #
    echo $SNW
    }
    
    getprefix() {
    if [ "$1" == "128.0.0.0" ]; then  result="/1"
    elif [ "$1" == "192.0.0.0" ]; then  result="/2"
    elif [ "$1" == "224.0.0.0" ]; then  result="/3"
    elif [ "$1" == "240.0.0.0" ]; then  result="/4"
    elif [ "$1" == "248.0.0.0" ]; then  result="/5"
    elif [ "$1" == "252.0.0.0" ]; then  result="/6"
    elif [ "$1" == "254.0.0.0" ]; then  result="/7"
    elif [ "$1" == "255.0.0.0" ]; then  result="/8"
    elif [ "$1" == "255.128.0.0" ];  then result="/9"
    elif [ "$1" == "255.192.0.0" ];  then result="/10"
    elif [ "$1" == "255.224.0.0" ];  then result="/11"
    elif [ "$1" == "255.240.0.0" ];  then result="/12"
    elif [ "$1" == "255.248.0.0" ];  then result="/13"
    elif [ "$1" == "255.252.0.0" ];  then result="/14"
    elif [ "$1" == "255.254.0.0" ];  then result="/15"
    elif [ "$1" == "255.255.0.0" ];  then result="/16"
    elif [ "$1" == "255.255.128.0" ];  then result="/17"
    elif [ "$1" == "255.255.192.0" ];  then result="/18"
    elif [ "$1" == "255.255.224.0" ];  then result="/19"
    elif [ "$1" == "255.255.240.0" ];  then result="/20"
    elif [ "$1" == "255.255.248.0" ];  then result="/21"
    elif [ "$1" == "255.255.252.0" ];  then result="/22"
    elif [ "$1" == "255.255.254.0" ];  then result="/23"
    elif [ "$1" == "255.255.255.0" ];  then result="/24"
    elif [ "$1" == "255.255.255.128" ];  then result="/25"
    elif [ "$1" == "255.255.255.192" ];  then result="/26"
    elif [ "$1" == "255.255.255.224" ];  then result="/27"
    elif [ "$1" == "255.255.255.240" ];  then result="/28"
    elif [ "$1" == "255.255.255.248" ];  then result="/29"
    elif [ "$1" == "255.255.255.252" ];  then result="/30"
    elif [ "$1" == "255.255.255.254" ];  then result="/31"
    elif [ "$1" == "255.255.255.255" ];  then result="/32"
    fi
    echo $result
    	}
    	
    ### end functions ############################################
    
    
    ## Assumptions:
    ## IF1 = router wan interface
    ## IF2 = router interface to secindary gateway, LAN in my case
    ## IP1 = router local WAN IP
    ## IP2 = router local LAN IP
    ## P1 = router remote WAN IP -> ISP IP (gateway) 
    ## P2 = router remote LAN IP --> a secon tomato connected ot the LAN in my case
    ## P1_NET = WAN net address + prefix (note netmask doesn't seem to be working so you'll need to use a prefix!)
    ## P2_NET = LAN net address + prefix (note netmask doesn't seem to be working so you'll need to use a prefix!)
    ##
    ##
    
    IF1=`nvram get wan_iface`  ## vlan 2 in my case you needn't touch this
    IF2=`nvram get lan_ifname` ## br0 in my case, you needn't touch this
    IP1=`nvram get wan_ipaddr` ## no need to touch this 
    IP2=`nvram get lan_ipaddr` ## you shouldn't need to change this but just in case...
    P1=`nvram get wan_gateway` ## no need to touch this
    P1M=`nvram get wan_netmask` ## no need to touch this
    P1P=`getprefix $P1M`        ## convet netmask into prefix e.g. 255.255.255.0 into /24
    P2=10.10.10.2              ## manually set! 
    P1_NETT=`getnetwork $P1 $P1M` ##Work out  network address given IP and netmask
    P1_NET="$P1_NETT$P1P"      ## build the destination ISP1 network using the X.X.X.X/MM convention
    P2_NET=10.10.10.0/24       ## this is the network connecting to the secondary gateway, in my case is the LAN. --> manually set
    W1=1 #Weight of gateway 1  ## 50% connection to Internet connection 1
    W2=1 #Weight of gateway 2  ## 50% connection to Internet connection 2
    
    ## Clear previous settings if any
    ip route flush table 1
    ip route flush table 2
    ip route del default
    ## Add main routing table to table 1
    ## ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table 1 $ROUTE ; done
    
    ip route add $P1_NET dev $IF1 src $IP1 table 1
    ip route add default via $P1 table 1
    ip route add $P2_NET dev $IF2 src $IP2 table 2
    ip route add default via $P2 table 2
    
    ## conversion between wan_netmask and prefix to be done! e.g. 255.255.255.0 = 24
    
    ip route del $P1_NET dev $IF1 src $IP1
    ip route add $P1_NET dev $IF1 src $IP1  ## Route each wan network out of the right internafe
    ip route del $P2_NET dev $IF2 src $IP2
    ip route add $P2_NET dev $IF2 src $IP2  ##
    
    ip rule add from $IP1 table 1
    ip rule add from $IP2 table 2
    
    ## Fianlly add the default route with 2 destinations and their own metrics
    ip route add default scope global nexthop via $P1 dev $IF1 weight $W1 nexthop via $P2 dev $IF2 weight $W2
    It's a bit too long for the WANUP script so just save it somewhere safe (jffs/cifs/usb) and call it from the wanup after a sleep 15

    Can I please get some help with point 2 now? I just need the kernel to be patched and recompiled. Thanks!
     
  6. mstombs

    mstombs Network Guru Member

    Great Stuff!

    When I needed a bash equivalent of 1 before (half-bridge modem script spoofing), the best I came up with was

    Code:
    #calculate subnet
    a="${IP%.*}";b="${IP#*.}";n="${NM%.*}";m="${NM#*.}"
    SNW=$((${IP%%.*}&${NM%%.*})).$((${b%%.*}&${m%%.*})).$((${a##*.}&${n##*.})).$((${IP##*.}&${NM##*.}))
    discussion http://www.routertech.org/viewtopic.php?f=28&t=1609

    Is that functionally equivalent to your solution?

    and here's a smaller cidr bash calculator with test program (based on linuxquestions)

    Code:
    #!/bin/sh
    
    # Function calculates number of bit in a netmask
    #
    mask2cidr() {
    n=0
    IFS=.
    for d in $1;do
    case $d in
    255) m=8;;
    254) m=7;;
    252) m=6;;
    248) m=5;;
    240) m=4;;
    224) m=3;;
    192) m=2;;
    128) m=1;;
    0) m=0;;
    *) echo "Error: $d is not recognised"; exit 1
    esac
    let n+=m
    done
    echo "$n"
    }
    
    ## main ##
    MASK=$1
    numbits=$(mask2cidr $MASK)
    echo "/$numbits"
    exit 0

    Would be much easier in C-code in the rc files of course!

    Chinese dualwan uses a bash shell ping script, but I agree would be much better to have kernel patched - I'll take a look.

    [edit] kernel patch is not straight-forward because TomatoUSB kernel not standard 2.6.22, some patches already present, others appear to conflict - definitely needs teddy_bear or other kernel hacker who knows what he is doing. If you want to see the messages try

    Code:
    ~/tomato.git/release/src-rt/linux/linux-2.6$ patch -p 2 --dry-run <routes-2.6.22-15.diff
     
  7. rs232

    rs232 Network Guru Member

    Hi :) The first function in my script it's based on the link you mentioned but "functionized" if that's the word to be used within the script. It appears to be working well.

    I haven't tested the script you mentioned but it look much shorter and therefore smarter than mine! I'll have a look if it's the case to replace mine with yours to keep things short (always good) and tidy.

    The patch I'm referring to is exclusively to add dead gateway detection e.g. you can ping google.com specifying the output interface and if unsuccessful act e.g. remove the gateway whose ping failed from the load balancing pool.

    If you have time try to install zentyal somewhere (vmware or so?), and check the network load-balancing section. you'll see immediately what I'm talking about :)

    Agreed, teddy_bears's mailbox though is full and he hasn't read this post so far apparently... I don't think there's anything else we can do other than wait. :frown:
     
  8. rs232

    rs232 Network Guru Member

    Ok here it goes script version 1.1. The getprefix is much shorter and smarter now, thanks! :smile1: :

    Code:
    ### Functions ###############################################
    
    getnetwork() {
    
    if [ "$2" ]; then
       NM="$2"
    else
       NM="255.255.255.0"
    fi
    if [ "$1" ]; then
       IP="$1"
    else
       IP="255.255.255.255"
    fi
    #
    n="${NM%.*}";m="${NM##*.}"
    l="${IP%.*}";r="${IP##*.}";c=""
    if [ "$m" = "0" ]; then
       c=".0"
       m="${n##*.}";n="${n%.*}"
       r="${l##*.}";l="${l%.*}"
       if [ "$m" = "0" ]; then
          c=".0$c"
          m="${n##*.}";n="${n%.*}"
          r="${l##*.}";l="${l%.*}"
          if [ "$m" = "0" ]; then
             c=".0$c"
             m=$n
             r=$l;l=""
          fi
       fi
    fi
    let s=256-$m
    let r=$r/$s*$s
    if [ "$l" ]; then
       SNW="$l.$r$c"
    else
       SNW="$r$c"
    fi
    #
    echo $SNW
    }
    
    getprefix() {
    n=0
    IFS=.
    for d in $1;do
    case $d in
    255) m=8;;
    254) m=7;;
    252) m=6;;
    248) m=5;;
    240) m=4;;
    224) m=3;;
    192) m=2;;
    128) m=1;;
    0) m=0;;
    *) echo "Error: $d is not recognised"; exit 1
    esac
    let n+=m
    done
    echo "/$n"
    }
    	
    ### end functions ############################################
    
    
    ## Assumptions:
    ## IF1 = router wan interface
    ## IF2 = router interface to secindary gateway, LAN in my case
    ## IP1 = router local WAN IP
    ## IP2 = router local LAN IP
    ## P1 = router remote WAN IP -> ISP IP (gateway) 
    ## P2 = router remote LAN IP --> a secon tomato connected ot the LAN in my case
    ## P1_NET = WAN net address + prefix (note netmask doesn't seem to be working so you'll need to use a prefix!)
    ## P2_NET = LAN net address + prefix (note netmask doesn't seem to be working so you'll need to use a prefix!)
    ##
    ##
    
    IF1=`nvram get wan_iface`  ## vlan 2 in my case you needn't touch this
    IF2=`nvram get lan_ifname` ## br0 in my case, you needn't touch this
    IP1=`nvram get wan_ipaddr` ## no need to touch this 
    IP2=`nvram get lan_ipaddr` ## you shouldn't need to change this but just in case...
    P1=`nvram get wan_gateway` ## no need to touch this
    P1M=`nvram get wan_netmask` ## no need to touch this
    P1P=`getprefix $P1M`        ## convet netmask into prefix e.g. 255.255.255.0 into /24
    P2=10.10.10.2              ## manually set! 
    P1_NETT=`getnetwork $P1 $P1M` ##Work out  network address given IP and netmask
    P1_NET="$P1_NETT$P1P"      ## build the destination ISP1 network using the X.X.X.X/MM convention
    P2_NET=10.10.10.0/24       ## this is the network connecting to the secondary gateway, in my case is the LAN. --> manually set
    W1=1 #Weight of gateway 1  ## 50% connection to Internet connection 1
    W2=1 #Weight of gateway 2  ## 50% connection to Internet connection 2
    
    ## Clear previous settings if any
    ip route flush table 1
    ip route flush table 2
    ip route del default
    ## Add main routing table to table 1
    ## ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table 1 $ROUTE ; done
    
    ip route add $P1_NET dev $IF1 src $IP1 table 1
    ip route add default via $P1 table 1
    ip route add $P2_NET dev $IF2 src $IP2 table 2
    ip route add default via $P2 table 2
    
    ## conversion between wan_netmask and prefix to be done! e.g. 255.255.255.0 = 24
    
    ip route del $P1_NET dev $IF1 src $IP1
    ip route add $P1_NET dev $IF1 src $IP1  ## Route each wan network out of the right internafe
    ip route del $P2_NET dev $IF2 src $IP2
    ip route add $P2_NET dev $IF2 src $IP2  ##
    
    ip rule add from $IP1 table 1
    ip rule add from $IP2 table 2
    
    ## Fianlly add the default route with 2 destinations and their own metrics
    ip route add default scope global nexthop via $P1 dev $IF1 weight $W1 nexthop via $P2 dev $IF2 weight $W2
     
  9. rs232

    rs232 Network Guru Member

    Another step forward:

    On both gateways (tomatos in my case) add this line in the scripts/firewall

    Code:
    echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter
     
  10. roadkill

    roadkill Super Moderator Staff Member Member

    bash scripts used in dual wan tomato

    Code:
    #!/bin/ash
    # Auto Routes(2WAN) Script VER 0.16 by rightzd 20090927
    
    LOGGER=logger
    LOCK_FILE=/tmp/policyroute-set.lock
    
    NETLIST=/tmp/policyroute-netlist
    if [ ! -f $NETLIST ]; then
        $LOGGER "$NETLIST does not exist!"
        exit 2
    fi
    
    $LOGGER "Start PolicyRouting ..."
    WAN1_GATEWAY=$(nvram get wan_gateway)
    WAN2_GATEWAY=$(nvram get wan2_gateway)
    WAN1_IFACE=$(nvram get wan_iface)
    WAN2_IFACE=$(nvram get wan2_iface)
    WAN1_IP=$(ifconfig $WAN1_IFACE|grep "inet addr"|awk -F ":" '{print $2}'|awk -F " " '{print $1}')
    WAN2_IP=$(ifconfig $WAN2_IFACE|grep "inet addr"|awk -F ":" '{print $2}'|awk -F " " '{print $1}')
    
    if [ "$WAN1_IFACE" = "$WAN2_IFACE" ]; then
      $LOGGER "Start PolicyRouting fail, WAN1_IFACE = WAN2_IFACE"
      exit
    fi
    
    if [ "$WAN1_IFACE" = "" ]; then
      $LOGGER "Start PolicyRouting fail, WAN1_IFACE is NULL"
      exit
    fi
    
    if [ "$WAN2_IFACE" = "" ]; then
      $LOGGER "Start PolicyRouting fail, WAN2_IFACE is NULL"
      exit
    fi
    
    if [ -f $LOCK_FILE ]; then
      $LOGGER "Start PolicyRouting exit, other process starting."
      exit
    fi
    
    echo "SETTING" > $LOCK_FILE
    
    $LOGGER "WAN1_IFACE:$WAN1_IFACE, WAN1_IP:$WAN1_IP, WAN1_GATEWAY:$WAN1_GATEWAY"
    $LOGGER "WAN2_IFACE:$WAN2_IFACE, WAN2_IP:$WAN2_IP, WAN2_GATEWAY:$WAN2_GATEWAY"
    
    $LOGGER "disable rp_filter "
    echo '0' > /proc/sys/net/ipv4/conf/all/rp_filter
    
    ip rule flush
    ip rule del table main
    ip rule del table default
    ip rule add lookup main prio 32766
    ip rule add lookup default prio 32767
    
    # WAN1 DNS Rule
    WAN1_GET_DNS=$(nvram get wan_get_dns)
    for WAN_DNS in $WAN1_GET_DNS
    do
        $LOGGER "set WAN1 route($WAN1_GATEWAY) for DNS:$WAN_DNS"
        if [ ! "$WAN_DNS" = "0.0.0.0" ]; then
            ip rule add to $WAN_DNS table 100 prio 150
        fi
    done
    
    # WAN2 DNS Rule
    WAN2_GET_DNS=$(nvram get wan2_get_dns)
    for WAN_DNS in $WAN2_GET_DNS
    do
        $LOGGER "set WAN2 route($WAN2_GATEWAY) for DNS:$WAN_DNS"
        if [ ! "$WAN_DNS" = "0.0.0.0" ]; then
            ip rule add to $WAN_DNS table 200 prio 150
        fi
    done
    
    # PPTP DNS Rule
    USE_PEERDNS=$(nvram get pptp_client_peerdns)
    if [ "$USE_PEERDNS" = "1" ]; then
        PPTP_GET_DNS=$(nvram get pptp_client_get_dns)
        for PPTP_DNS in $PPTP_GET_DNS
        do
            if [ ! "$PPTP_DNS" = "0.0.0.0" ]; then
                ip rule add to $PPTP_DNS table 250 prio 149
            fi
        done
    fi
    
    # 2. set fixed route rules
    if [ -f $NETLIST ]; then
        $LOGGER "set WAN2 route rules (WAN2 rules lookup table 200)..."
        MY_LINE_NO=1
        while read MY_LINE
        do
            if [ ! "$MY_LINE" = "" ]; then
              ip rule add to $MY_LINE table 200 prio 200
              MY_LINE_NO=$((MY_LINE_NO+1))
             fi
        done < $NETLIST
    fi
    
    #3. set WAN1 route table
    $LOGGER "set WAN1 route table ..."
    ip route flush table 100
    ip route | while read ROUTE 
    do 
      if [ ! "$ROUTE" = "default" ]; then
        ip route append table 100 to $ROUTE 
      fi
    done
    ip route del table 100 default
    ip route del table 100 default
    ip route del table 100 default
    ip route del table 100 default
    ip route del table 100 default 
    ip route add table 100 default via $WAN1_GATEWAY dev $WAN1_IFACE src $WAN1_IP
    ip rule add from $WAN1_IP table 100 prio 100
    
    #4. set WAN2 route table
    $LOGGER "set WAN2 route table ..."
    ip route flush table 200
    ip route | while read ROUTE 
    do 
      if [ ! "$ROUTE" = "default" ]; then
        ip route append table 200 to $ROUTE 
      fi
    done 
    ip route del table 200 default
    ip route del table 200 default
    ip route del table 200 default
    ip route del table 200 default
    ip route del table 200 default
    ip route add table 200 default via $WAN2_GATEWAY dev $WAN2_IFACE src $WAN2_IP
    ip rule add from $WAN2_IP table 200 prio 100
    
    # 8. AssignOUT 规则
    # wan1
    ip rule add fwmark 0x100/0xf00 table 100 prio 110
    # wan2
    ip rule add fwmark 0x200/0xf00 table 200 prio 110
    # vpn, 已经在pptp.c中实现
    #ip rule add fwmark 0x500/0xf00 table 250 prio 110
    
    # 9. 自定义规则写这里,prio 100表示优先级,数字越小优先级越高
    # 目标IP是1.1.1.1的走WAN1
    # ip rule add to 1.1.1.1 table 100 prio 100
    # 目标IP是2.2.2.2的走WAN2
    # ip rule add to 2.2.2.2 table 100 prio 100
    # 来源IP是192.168.1.100的走WAN1
    # ip rule add from 192.168.1.100 table 100 prio 100
    # 来源IP是192.168.1.200的走WAN2
    # ip rule add from 192.168.1.100 table 200 prio 100
    # 9. 自定义规则结束
    
    $LOGGER "set WAN1 is default router "
    ip route del default
    ip route del default
    ip route del default
    ip route del default
    ip route del default
    ip route add default via $WAN1_GATEWAY dev $WAN1_IFACE src $WAN1_IP
    
    $LOGGER "clear route cache..."
    ip route flush cache
    
    $LOGGER "Start PolicyRouting success."
    rm $LOCK_FILE
    Code:
    #!/bin/ash
    # common-stop Script VER 0.5 by rightzd 20090919
    LOGGER=logger
    LOCK_FILE=/var/policyroute-unset.lock
    
    $LOGGER "Stop PolicyRouting ..."
    WAN1_GATEWAY=$(nvram get wan_gateway)
    WAN2_GATEWAY=$(nvram get wan2_gateway)
    WAN1_IFACE=$(nvram get wan_iface)
    WAN2_IFACE=$(nvram get wan2_iface)
    
    if [ -f $LOCK_FILE ]; then
      $LOGGER "Stop PolicyRouting exit, other process stoping."
      exit
    fi
    
    echo "SETTING" > $LOCK_FILE
    
    # when line disconnected, system is auto remove routes
    if [ "$WAN1_IFACE" != "" ]; then
      ip route replace default via $WAN1_GATEWAY dev $WAN1_IFACE
    else
      $LOGGER "WAN1 disconnectd!"
      ip route flush table 100 
    fi
    
    if [ "$WAN2_IFACE" != "" ]; then
      ip route replace default via $WAN2_GATEWAY dev $WAN2_IFACE
    else
      $LOGGER "WAN2 disconnectd!"
      ip route flush table 200  
    fi
    
    $LOGGER "clear route cache..."
    ip route flush cache
    
    $LOGGER "Stop PolicyRouting success."
    rm $LOCK_FILE
    Code:
    #!/bin/ash
    # load-balance(2WAN) Script VER 0.16 by rightzd 20090919
    
    LOGGER=logger
    LOCK_FILE=/var/policyroute-set.lock
    NETLIST=/var/policyroute-netlist
    
    $LOGGER "Start PolicyRouting ..."
    WAN1_GATEWAY=$(nvram get wan_gateway)
    WAN2_GATEWAY=$(nvram get wan2_gateway)
    WAN1_IFACE=$(nvram get wan_iface)
    WAN2_IFACE=$(nvram get wan2_iface)
    WAN1_IP=$(ifconfig $WAN1_IFACE|grep "inet addr"|awk -F ":" '{print $2}'|awk -F " " '{print $1}')
    WAN2_IP=$(ifconfig $WAN2_IFACE|grep "inet addr"|awk -F ":" '{print $2}'|awk -F " " '{print $1}')
    WAN1_WEIGHT=$(nvram get xwan_wan1_weight)
    WAN2_WEIGHT=$(nvram get xwan_wan2_weight)
    
    if [ "$WAN1_WEIGHT" = "" ]; then
      WAN1_WEIGHT=1
    fi
    
    if [ "$WAN2_WEIGHT" = "" ]; then
      WAN2_WEIGHT=1
    fi
    
    if [ "$WAN1_IFACE" = "$WAN2_IFACE" ]; then
      $LOGGER "Start PolicyRouting fail, WAN1_IFACE = WAN2_IFACE"
      exit
    fi
    
    if [ "$WAN1_IFACE" = "" ]; then
      $LOGGER "Start PolicyRouting fail, WAN1_IFACE is NULL"
      exit
    fi
    
    if [ "$WAN2_IFACE" = "" ]; then
      $LOGGER "Start PolicyRouting fail, WAN2_IFACE is NULL"
      exit
    fi
    
    if [ -f $LOCK_FILE ]; then
      $LOGGER "Start PolicyRouting exit, other process starting."
      exit
    fi
    
    echo "SETTING" > $LOCK_FILE
    
    $LOGGER "WAN1_IFACE:$WAN1_IFACE, WAN1_IP:$WAN1_IP, WAN1_GATEWAY:$WAN1_GATEWAY"
    $LOGGER "WAN2_IFACE:$WAN2_IFACE, WAN2_IP:$WAN2_IP, WAN2_GATEWAY:$WAN2_GATEWAY"
    
    $LOGGER "disable rp_filter "
    echo '0' >/proc/sys/net/ipv4/conf/all/rp_filter
    
    #1. set ip rules
    ip rule flush
    ip rule del table main
    ip rule del table default
    ip rule add lookup main prio 32766
    ip rule add lookup default prio 32767
    
    # WAN1 DNS Rule
    WAN1_GET_DNS=$(nvram get wan_dns)
    if [ "$WAN1_GET_DNS" = "" ]; then
      WAN1_GET_DNS=$(nvram get wan_get_dns)
    fi
    for WAN_DNS in $WAN1_GET_DNS
    do
        $LOGGER "set WAN1 route($WAN1_GATEWAY) for DNS:$WAN_DNS"
        if [ ! "$WAN_DNS" = "0.0.0.0" ]; then
            ip rule add to $WAN_DNS table 100 prio 150
        fi
    done
    
    # WAN2 DNS Rule
    WAN2_GET_DNS=$(nvram get wan2_dns)
    if [ "$WAN2_GET_DNS" = "" ]; then
      WAN2_GET_DNS=$(nvram get wan2_get_dns)
    fi
    for WAN_DNS in $WAN2_GET_DNS
    do
        $LOGGER "set WAN2 route($WAN2_GATEWAY) for DNS:$WAN_DNS"
        if [ ! "$WAN_DNS" = "0.0.0.0" ]; then
            ip rule add to $WAN_DNS table 200 prio 150
        fi
    done
    
    # PPTP DNS Rule
    USE_PEERDNS=$(nvram get pptp_client_peerdns)
    if [ "$USE_PEERDNS" = "1" ]; then
        PPTP_GET_DNS=$(nvram get pptp_client_get_dns)
        for PPTP_DNS in $PPTP_GET_DNS
        do
           if [ ! "$PPTP_DNS" = "0.0.0.0" ]; then
               ip rule add to $PPTP_DNS table 250 prio 149
           fi
        done
    fi
    
    #2. set fixed route rule
    $LOGGER "set QQ&MSN via WAN1..."
    if [ -f $NETLIST ]; then
            MY_LINE_NO=1
            while read MY_LINE
            do
              ip rule add to $MY_LINE table 100 prio 200
              MY_LINE_NO=$((MY_LINE_NO+1))
            done < $NETLIST
    fi
    
    #3. set WAN1 route table
    $LOGGER "set route table 100..."
    ip route flush table 100
    ip route | while read ROUTE 
    do 
      if [ ! "$ROUTE" = "default" ]; then
        ip route append table 100 to $ROUTE 
      fi
    done
    ip route del table 100 default
    ip route del table 100 default
    ip route del table 100 default
    ip route del table 100 default
    ip route del table 100 default 
    ip route add table 100 default via $WAN1_GATEWAY dev $WAN1_IFACE src $WAN1_IP
    ip rule add from $WAN1_IP table 100 prio 100
    
    #3. set WAN2 route table
    $LOGGER "set route table 200..."
    ip route flush table 200
    ip route | while read ROUTE 
    do 
      if [ ! "$ROUTE" = "default" ]; then
        ip route append table 200 to $ROUTE 
      fi
    done 
    ip route del table 200 default
    ip route del table 200 default
    ip route del table 200 default
    ip route del table 200 default
    ip route del table 200 default
    ip route add table 200 default via $WAN2_GATEWAY dev $WAN2_IFACE src $WAN2_IP
    ip rule add from $WAN2_IP table 200 prio 100
    
    #8. AssignOUT 规则
    # wan1
    ip rule add fwmark 0x100/0xf00 table 100 prio 110
    # wan2
    ip rule add fwmark 0x200/0xf00 table 200 prio 110
    # vpn, 已经在pptp.c中实现
    #ip rule add fwmark 0x500/0xf00 table 250 prio 110
    
    #9. 自定义规则起始
    #自定义规则写这里
    #9. 自定义规则结束
    
    #10. 设置默认路由为负载均衡
    $LOGGER "set default router with load-balance"
    ip route del default
    ip route del default
    ip route del default
    ip route del default
    ip route del default
    ip route add default scope global nexthop via $WAN1_GATEWAY dev $WAN1_IFACE weight $WAN1_WEIGHT nexthop via $WAN2_GATEWAY dev $WAN2_IFACE weight $WAN2_WEIGHT
    
    $LOGGER "clear route cache..."
    ip route flush cache
    
    $LOGGER "Start PolicyRouting success."
    rm $LOCK_FILE
    I am willing to help PM me.

    :grin:
     
  11. rs232

    rs232 Network Guru Member

    Can I say: wow!?! :biggrin:

    Can anybody translate the Chinese bits in the scripts please? They seems to be comments but they may help a lot!

    So... unless a kernel/patching modification is also needed we shouldn't bee too far.

    I'm getting excited now lol!
     
  12. WifiShadow

    WifiShadow Networkin' Nut Member

  13. rs232

    rs232 Network Guru Member

    Thanks! That helps :)
    Can anybody gently post the screenshots of the dualwan gui english version please?

    Thanks!
     

Share This Page