Ich nutze seit einiger Zeit einen 2. DSL-Zugang als Backup und wollte diesen unter einen Hut mit dem schon bestehenden ursprünglichen Zugang bringen.
In meinem LAN nutze ich einen Router ähnlich dem allseits beliebten Linksys WRT54G mit Tomato-Firmware. Da diese Router bzw. auch die dafür erhältlichen Firmwares prinzipiell nur für die Nutzung eines Internet-Zugangs ausgelegt sind, habe ich mein System entsprechend angepasst, um beide Internetverbindungen gleichzeitig und parallel nutzen zu können.
Da das Vorhaben in Summe nicht ganz so trivial war, lt. Infos im Internet aber immer wieder mal Interesse so einem DualWAN-Router besteht, habe ich mich entschlossen hier ein kleines HowTo zu schreiben.
HOWTO: Zeitgleicher Betrieb 2er Internet-Verbindungen mit Tomato (Dual-WAN)
Einleitung
Was ermöglicht diese DUAL-WAN-Lösung:
- Anbinden eines 2. WAN-Uplinks (zB 2. Modem eines 2. Zugangs) an einen Tomato-Router
- Übernahme der Remote-Services (SSH, Remote-Webinterface) auf das 2. WAN-Interface (damit sind die Dienste auch über die IP des 2. Zugangs erreichbar)
- Übernahme der Portforwarding-Einstellungen auf das 2. WAN-Interface
- Optional aktivierbar: Round Robin Load-Balancing
- Optional konfigurierbar: Definierbares statisches Routing für bestimmte Verbindungen (zB Verbindungen zum Firmen-VPN-Server generell immer über das 2. Modem, da dieser Zugang zB die erforderliche fixe IP hat)
- Zukünftig / in Arbeit: Failover-Mechanismus: Umlenken des Traffics auf den Ersatz-Zugang, sobald einer ausfällt
Was klappt mit dieser Modifizierung NICHT:
- QOS - habe ich im DUAL-WAN-Betrieb noch nicht aktiviert --> Lösung: Ausweichen auf TCP Vegas, od. Erweiterung der Scripts weiter unten um QOS-Unterstützung
- Volle Anzahl Switch-Ports - leider muss einer der Ethernet-Ports vom LAN-seitigen Switch entkoppelt werden, um daran das Modem des 2. Internet-Zugangs zu betreiben. Die Anzahl der LAN-Ports vermindert sich so um 1
Voraussetzungen:
- TomatoUSB (es reicht die Mini-Version)- leider fehlt der ursprünglichen Version von Tomato die MULTIPATH-Option im verwendeten Kernel, d.h. für den Dual-WAN-Betrieb muss auf TomatoUSB ausgewichen werden, welches die erforderliche Unterstützung im Kernel mit ein kompiliert hat
- Tomato-kompatibler Router - für das System sind alle Tomato-kompatiblen Router geeignet, sowie einige "exklusiv" von TomatoUSB unterstützten Modelle; Übersicht: http://tomatousb.org/doc:build-types
- 2 Modems / Router für die Internet-Zugänge, ansprechbar über verschiedene IP-Adressen in verschiedenen Subnetzen (sind entsprechend zu konfigurieren)
- Optional: Portworwarding auf den Internet-Routern aller Ports auf den jeweils mit dem Modem verbundenen WAN-Port des Tomato-Routers - falls der Router bzw. das eigene LAN von außen erreichbar sein soll; Anmerkung: Meine Speedtouch 585v7 zicken herum, wenn ich alle Port weiterleite. Ich leite deshalb jeweils die Ports 1-65000 (UDP und TCP) an den WAN-Port des Tomto-Routers weiter --> ein guter Kompromiss
Übersicht Netzwerk-Aufbau
- Code: Alles auswählen
- /--------------\
 | |
 10.0.0.138/24| ST585 v7 |IP1
 ---------------| |---
 /------------------------\ / PF 1-65000 | DSL 1 |
 | | 10.0.0.1/24 / -> 10.0.0.1 | |
 | Linksys |-------------- \--------------/
 | WRN2000v2 | vlan1
 192.168.0.1/24| | /--------------\
 ---------------| Firmware | 10.1.0.1/24 | |
 br0 ((W)LAN) | TomatoUSB-Mod |--------------\ 10.1.0.138/24| ST585 v7 |IP2
 | www.tomatousb.org | vlan2 \---------------| |---
 | | PF 1-65000 | DSL 2 |
 \------------------------/ -> 10.1.0.1 | |
 \--------------/
Einrichtung
1. Vorbereitung / Einrichtung 2. WAN-Port
Wie oben schon angeführt wird einer der Ethernet-Ports die ursprünglich für das LAN verwendet werden, der Port zum Verbinden des 2. Internet-Modems.
Ich hab mich bei mir für den Port unmittelbar neben dem WAN-Port entschieden (bei den LEDs am Gerät als Port 4 bezeichnet)
Um dem Switch einen Ethernet-Port wegzunehmen, sehen wir uns erst mal die aktuelle Port-Zuweisung für die LAN-Schnittstelle (Switch) an:
- Code: Alles auswählen
- root@router:/tmp/home/root# nvram get vlan0ports
 4 3 2 1 5*
Bei meinem Router war der vorletzte Port (1) jener unmittelbar nebem dem WAN-Interface (Achtung: Hier ist er als "1" bezeichnet, auf der Vorderseite des Gehäuses (LEDs) in umgekehrter Reihenfolge als "4")
Je nach Routermodell könnte der Port neben dem WAN-Interface auch der erste in der obigen Liste sein. Ist man sich nicht ganz sicher muss man probieren - es sollte aber meines Wissens nach entweder der 1. in der Liste oder der vorletzte Port in der Liste sein. Natürlich steht die Wahl des zu verwendeten LAN-Ports einem völlig frei - ich allerdings habe mich für den neben dem WAN-Port entschieden.
Hat man sich für einen Port entschieden (in meinem Fall die Nr. "1" lt. obiger Liste), so muss dieser nun aus dem LAN-Switch ausgehängt werden.
- Code: Alles auswählen
- nvram set vlan0ports="4 3 2 5*"
Danach wird gleich noch ein neues Netzwerk-Interface angelegt + der soeben freigemacht Port dem neuen Device zugewiesen --> das ist später das 2. WAN-Device.
- Code: Alles auswählen
- nvram set vlan2ports="1 5"
 nvram set vlan2hwname=et0
 nvram set wan2_ifname=vlan2
Im Anschluss daran setzen wir gleich noch die IP-Konfiguration für das neue WAN-Interface, die in weitere Folge dann von den Init-Scripts weiter unten ausgelesen wird.
- Code: Alles auswählen
- nvram set wan2_ipaddr="10.1.0.1"
 nvram set wan2_netmask="255.255.255.0"
 nvram set wan2_gateway="10.1.0.138"
 nvram set wan2_dns="10.1.0.138"
Zum Abschluss noch ein
- Code: Alles auswählen
- nvram commit
Damit wäre die Konfiguration auf der Shell abgeschlossen. Nach einem Reboot wird diese übernommen und ifconfig -a sollte bereits ein zusätzliches Netzwerk-Interface "vlan2" anzeigen (das zu diesem Zeitpunkt allerdings noch nicht konfiguriert und aktiv ist)
2. Aktivierung DUAL-WAN-Betrieb
Nun zur eigentlichen Sache, der Inbetriebnahme der Dual-WAN-Fähigkeiten des Routers.
Dies geschieht ganz einfach über das Webinterface des Routers, im Bereich Administration / Scripts
Im Tab Firewall den folgenden Inhalt ablegen, mittels Copy/Paste (anderen Inhalt vorher löschen, falls vorhanden):
- Code: Alles auswählen
- #!/bin/sh
 ######################
 #
 # Script DUAL-WAN
 # CORE
 #
 # for TomatoUSB 1.28
 #
 # Date: 2010-09-04
 #
 ######################
 ####
 ##
 ## USER-CONFIG
 ##
 ####
 ### Enables (1) oder disables (0) kernel based
 ### load balancing between the 2 WAN connections
 ENABLE_KERNEL_WAN_LOAD_BALANCING=1
 ####
 ##
 ## CONSTANTS
 ##
 ####
 ### Internal config
 FOLDER_DUALWAN=/tmp/dualwan
 FILE_DUALWAN_CONFIGURED=$FOLDER_DUALWAN/configured
 SCRIPT_EXTENSION_NVRAM=script_shut
 SCRIPT_EXTENSION_FS=$FOLDER_DUALWAN/dualwan_extension.sh
 CONFIG_FILES_KERNEL_REVERSEPATH_FILTERING=/proc/sys/net/ipv4/conf/*/rp_filter
 TABLE_WAN1=100
 TABLE_WAN2=200
 MARK_WAN1=0x100
 MARK_WAN2=0x200
 ### NVRAM stored config
 WAN_IFNAME=`nvram get wan_ifname`
 WAN_IPADDR=`nvram get wan_ipaddr`
 WAN_GATEWAY=`nvram get wan_gateway`
 WAN_DNS=`nvram get wan_dns`
 WAN2_IFNAME=`nvram get wan2_ifname`
 WAN2_IPADDR=`nvram get wan2_ipaddr`
 WAN2_NETMASK=`nvram get wan2_netmask`
 WAN2_GATEWAY=`nvram get wan2_gateway`
 WAN2_DNS=`nvram get wan2_dns`
 LAN_IPADDR=`nvram get lan_ipaddr`
 PORT_FORWARDING_CONFIGURATION=`nvram get portforward`
 PING_FROM_WAN_BLOCKED=`nvram get block_wan`
 HTTPD_REMOTE_ENABELD=`nvram get remote_management`
 HTTPD_REMOTE_HTTPS_ENABLED=`nvram get remote_mgt_https`
 HTTPD_WANPORT=`nvram get http_wanport`
 HTTPD_LANPORT=`nvram get http_lanport`
 HTTPD_LANPORT_HTTPS=`nvram get https_lanport`
 SSHD_REMOTE_ENABLED=`nvram get sshd_remote`
 SSHD_REMOTE_PORT=`nvram get sshd_rport`
 SSHD_PORT=`nvram get sshd_port`
 ###
 ##
 ## Function library
 ##
 ###
 configureWan2Device() {
 ### skip if already configured
 if test -e $FILE_DUALWAN_CONFIGURED;
 then
 return
 fi
 logger "Setting up second WAN-device: interface $WAN2_IFNAME, ip $WAN2_IPADDR, netmask $WAN2_NETMASK"
 ifconfig $WAN2_IFNAME $WAN2_IPADDR netmask $WAN2_NETMASK up
 mkdir -p `dirname $FILE_DUALWAN_CONFIGURED`
 touch $FILE_DUALWAN_CONFIGURED
 }
 expandRoutingTablesAndRules() {
 ### rules
 ip rule flush
 ip rule add lookup main prio 32766
 ip rule add lookup default prio 32767
 ip rule add from $WAN_IPADDR table $TABLE_WAN1 prio 100
 ip rule add fwmark $MARK_WAN1 table $TABLE_WAN1 prio 101
 ip rule add from $WAN2_IPADDR table $TABLE_WAN2 prio 200
 ip rule add fwmark $MARK_WAN2 table $TABLE_WAN2 prio 201
 ### routing tables
 ip route flush table $TABLE_WAN1 >/dev/null 2>&1
 ip route flush table $TABLE_WAN2 >/dev/null 2>&1
 for TABLE in $TABLE_WAN1 $TABLE_WAN2
 do
 ip route | grep link | while read ROUTE
 do
 ip route add table $TABLE to $ROUTE
 done
 done
 ip route add table $TABLE_WAN1 default via $WAN_GATEWAY
 ip route add table $TABLE_WAN2 default via $WAN2_GATEWAY
 }
 expandIptables() {
 ### filter table
 checkIptablesFilterTableExpanded
 if [ $? -ne 0 ];
 then
 expandIptablesFilterTable
 fi
 ### nat table
 expandIptablesNatTable
 }
 checkIptablesFilterTableExpanded() {
 iptables --list -v |grep -q $WAN2_IFNAME
 }
 expandIptablesFilterTable() {
 iptables -I INPUT 2 -i br0 -d $WAN2_IPADDR -j DROP
 positionWanRules=`iptables --list FORWARD -v --line-numbers | grep -m 1 $WAN_IFNAME | sed -n "s/\([0-9]\+\).*/\1/p"`
 iptables -I FORWARD `expr $positionWanRules + 2` -i $WAN2_IFNAME -j wanin
 iptables -I FORWARD `expr $positionWanRules + 3` -o $WAN2_IFNAME -j wanout
 }
 expandIptablesNatTable() {
 lanNet=`iptables --list PREROUTING -v -t nat --line-numbers |sed -n "s/^1.* \(\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\/[0-9]\{2\}\)/\1/p"`
 iptables -t nat -I PREROUTING 2 -i $WAN2_IFNAME -d $lanNet -j DROP
 iptables -t nat -A POSTROUTING -o $WAN2_IFNAME -j MASQUERADE
 }
 enableDualWanRouting() {
 enableDualWanRoutingSetUpIptablesEntries
 enableDualWanRoutingConfigureKernelRpFilter
 }
 enableDualWanRoutingSetUpIptablesEntries() {
 ### Set connmark for new incoming (--> not already marked) connections according to their iface
 iptables -t mangle -A PREROUTING -i $WAN_IFNAME -m connmark --mark 0 -j CONNMARK --set-mark $MARK_WAN1
 iptables -t mangle -A PREROUTING -i $WAN2_IFNAME -m connmark --mark 0 -j CONNMARK --set-mark $MARK_WAN2
 ### Set packet mark from connmark for already marked (--> established and new incoming-> see rules obove) connections
 iptables -t mangle -A PREROUTING -m connmark ! --mark 0 -j CONNMARK --restore-mark
 iptables -t mangle -A OUTPUT -m connmark ! --mark 0 -j CONNMARK --restore-mark
 ### Set connmark if unmarked packages (--> packages of new connections) passing an WAN interface,
 ### according to the kernel made routing decision
 iptables -t mangle -A POSTROUTING -o $WAN_IFNAME -m connmark --mark 0 -j CONNMARK --set-mark $MARK_WAN1
 iptables -t mangle -A POSTROUTING -o $WAN2_IFNAME -m connmark --mark 0 -j CONNMARK --set-mark $MARK_WAN2
 }
 enableDualWanRoutingConfigureKernelRpFilter() {
 ### Disable reverse path filtering for all devices
 for rpFilterConfigFile in `ls $CONFIG_FILES_KERNEL_REVERSEPATH_FILTERING`;
 do
 echo 0 > $rpFilterConfigFile
 done
 }
 setUpRemoteServices() {
 ### Remote-Ping
 if [ $PING_FROM_WAN_BLOCKED -eq 0 ];
 then
 iptables -t nat -A PREROUTING -p icmp -d $WAN2_IPADDR -j DNAT --to $LAN_IPADDR
 fi
 ### Remote-Web-Access
 if [ $HTTPD_REMOTE_ENABELD -ne 0 ];
 then
 if [ $HTTPD_REMOTE_HTTPS_ENABLED -ne 0 ];
 then
 localWanHttpdPort=$HTTPD_LANPORT_HTTPS;
 else
 localWanHttpdPort=$HTTPD_LANPORT;
 fi
 iptables -t nat -A PREROUTING -p tcp --dport $HTTPD_WANPORT -d $WAN2_IPADDR -j DNAT --to $LAN_IPADDR:$localWanHttpdPort
 fi
 ### Remote-SSH
 if [ $SSHD_REMOTE_ENABLED -ne 0 ];
 then
 iptables -t nat -A PREROUTING -p tcp --dport $SSHD_REMOTE_PORT -d $WAN2_IPADDR -j DNAT --to $LAN_IPADDR:$SSHD_PORT
 fi
 }
 enablePortForwardingWan2() {
 oldIFS="$IFS"
 IFS=">"
 ### traverse each defined rule
 for portForwardingEntry in $PORT_FORWARDING_CONFIGURATION;
 do
 # parse current rule
 ruleEnabled=`echo $portForwardingEntry |cut -d "<" -f 1`
 protocol=`echo $portForwardingEntry |cut -d "<" -f 2`
 sourceAddress=`echo $portForwardingEntry |cut -d "<" -f 3`
 sourcePort=`echo $portForwardingEntry |cut -d "<" -f 4`
 destinationPort=`echo $portForwardingEntry |cut -d "<" -f 5`
 destinationAddress=`echo $portForwardingEntry |cut -d "<" -f 6`
 ruleName=`echo $portForwardingEntry |cut -d "<" -f 7`
 # skip disabled rules
 if [ "$ruleEnabled" -ne 1 ];
 then
 continue
 fi
 # deny forwarding of multiple ports --> not yet implemented
 if echo $sourcePort |grep -q -e "[:,]";
 then
 logger "Forwarding of multiple ports not yet implemented! NOT setting up forwarding rule $ruleName for 2nd WAN-device"
 continue
 fi
 ### rewrite variables
 # source address
 if [ -z "$sourceAddress" ];
 then
 sourceAddress="0.0.0.0"
 fi
 # destination address
 if [ -z "$destinationPort" ];
 then
 destinationPort=$sourcePort
 fi
 ### set up iptables rules
 # tcp
 if [ $protocol -eq 1 -o $protocol -eq 3 ];
 then
 iptables -t nat -A PREROUTING -p tcp --dport $sourcePort -d $WAN2_IPADDR -j DNAT --to $destinationAddress:$destinationPort
 fi
 # udp
 if [ $protocol -eq 2 -o $protocol -eq 3 ];
 then
 iptables -t nat -A PREROUTING -p udp --dport $sourcePort -d $WAN2_IPADDR -j DNAT --to $destinationAddress:$destinationPort
 fi
 done
 IFS=$oldIFS
 }
 setUpKernelConnectionLoadBalancing() {
 if [ $ENABLE_KERNEL_WAN_LOAD_BALANCING -ne 0 ];
 then
 ip route change default scope global equalize nexthop via $WAN_GATEWAY dev $WAN_IFNAME nexthop via $WAN2_GATEWAY dev $WAN2_IFNAME
 else
 ip route change default via $WAN_GATEWAY dev $WAN_IFNAME
 fi
 }
 finalizeConfiguration() {
 ### Flush routing cache
 ip route flush cache
 }
 ###
 ##
 ## Execution
 ##
 ###
 ### Core config
 configureWan2Device
 expandRoutingTablesAndRules
 expandIptables
 enableDualWanRouting
 setUpRemoteServices
 enablePortForwardingWan2
 setUpKernelConnectionLoadBalancing
 finalizeConfiguration
 ### Extended external config
 nvram get $SCRIPT_EXTENSION_NVRAM > $SCRIPT_EXTENSION_FS
 chmod u+x $SCRIPT_EXTENSION_FS
 $SCRIPT_EXTENSION_FS
Im Tab Shutdown den folgenden Inhalt ablegen, mittels Copy/Paste (anderen Inhalt vorher löschen, falls vorhanden):
Anmerkung: Das Script wird nicht tatsächlich beim Shutdown ausgeführt - die Ablage hier ist lediglich ein Workaround, da im Bereich Firewall die Scriptgröße auf insgesamt 8 KByte beschränkt ist; Das Script hier wird implizit vom Firewall-Script aufgerufen mit zur richtigen Zeit mit ausgeführt
- Code: Alles auswählen
- #!/bin/sh
 ######################
 #
 # Script DUAL-WAN
 # EXTENDED CONFIG
 #
 # for TomatoUSB 1.28
 #
 # Date: 2010-09-04
 #
 ######################
 ### This script is not intended to be executed from Tomato
 if echo $0 |grep -q script;
 then
 exit 0
 fi
 ####
 ##
 ## USER-CONFIG
 ##
 ####
 ### List of destinations to be routed via a specific interface,
 ### delimited by ","
 ###
 ### Destination: IP, Port or IP:Port
 ### Example: 1.2.3.4,4.4.4.4:80,22
 DESTINATIONS_WAN1=
 DESTINATIONS_WAN2=1.2.3.4,8080,195.3.96.67:53
 ####
 ##
 ## CONSTANTS
 ##
 ####
 MARK_WAN1=0x100
 MARK_WAN2=0x200
 ###
 ##
 ## Function library
 ##
 ###
 setUpStaticRouting() {
 if [ -z $1 -o -z $2 ];
 then
 return
 fi
 destinations=$1
 connectionMark=$2
 oldIFS=$IFS
 IFS=","
 for destination in $destinations;
 do
 if echo $destination |grep -q ":";
 then
 destinationIp=`echo $destination |cut -d ":" -f 1`
 destinationPort=`echo $destination |cut -d ":" -f 2`
 iptables -t mangle -I PREROUTING -p tcp -d $destinationIp --dport $destinationPort -m connmark --mark 0 -j CONNMARK --set-mark $connectionMark
 iptables -t mangle -I PREROUTING -p udp -d $destinationIp --dport $destinationPort -m connmark --mark 0 -j CONNMARK --set-mark $connectionMark
 else
 if echo $destination |grep -q "\.";
 then
 iptables -t mangle -I PREROUTING -d $destination -m connmark --mark 0 -j CONNMARK --set-mark $connectionMark
 else
 iptables -t mangle -I PREROUTING -p tcp --dport $destination -m connmark --mark 0 -j CONNMARK --set-mark $connectionMark
 iptables -t mangle -I PREROUTING -p udp --dport $destination -m connmark --mark 0 -j CONNMARK --set-mark $connectionMark
 fi
 fi
 done
 IFS=$oldIFS
 }
 ###
 ##
 ## Execution
 ##
 ###
 setUpStaticRouting $DESTINATIONS_WAN1 $MARK_WAN1
 setUpStaticRouting $DESTINATIONS_WAN2 $MARK_WAN2
3. Anpassung der Konfiguration
Die so hochgeladene Konfiguration kann nun noch den eigenen Wünschen entsprechend angepasst werden.
Das umfasst folgende Möglichkeiten:
- Aktivierung/Deaktivierung Round Robin Load Balancing
- Festlegen statischer Routen (Ziele zu denen immer über das selbe Modem verbunden wird)
Die Konfiguration ist jeweils zu Beginn der beiden Scripte anpassbar.
Round Robin Load Balancing
CORE-Script (Firewall-Tab)
- Code: Alles auswählen
- ####
 ##
 ## USER-CONFIG
 ##
 ####
 ### Enables (1) oder disables (0) kernel based
 ### load balancing between the 2 WAN connections
 ENABLE_KERNEL_WAN_LOAD_BALANCING=0
Static Routing
EXTENED CONFIG - Script (Shutdown-Tab)
- Code: Alles auswählen
- ####
 ##
 ## USER-CONFIG
 ##
 ####
 ### List of destinations to be routed via a specific interface,
 ### delimited by ","
 ###
 ### Destination: IP, Port or IP:Port
 ### Example: 1.2.3.4,4.4.4.4:80,22
 DESTINATIONS_WAN1=
 DESTINATIONS_WAN2=1.2.3.4,8080,195.3.96.67:53
(Das Beispiel hier routet bestimmte Verbindungen immer über den 2. Internet-Zugang - die Konfiguration für den 1. bleibt jedoch leer --> also keine Verbindungen statisch über diese Leitung routen --> kann natürlich jederzeit geändert werden)
4. Abschluss
Nach einem Speichern der so im Webinterface angelegten Scripts und einem Reboot ist die Konfiguration aktiv. Fertig!
Anmerkungen
Für Wünsche, Anregungen und sonstige Vorschläge bin ich natürlich jederzeit offen - auch Ergänzungen und Anpassungen der Skripte werden gerne angenommen


