Normalerweise erfolgt das Routing auf Basis des Ziels (Destination). Es gibt jedoch auch viele Fälle wo man das Routing basierend auf der Quelle eines Paketes machen will. Oft hört man auch den Ausdruck Source Based Routing dafür. Genau genommen ist das aber nur eine Teilmenge des Policy Based Routing.
Das Prinzip ist recht einfach: man markiert in der Firewall (mangle/prerouting) die gewünschten Pakete und kann dann auf Basis dieser Markierung spezifische Routingtabellen laden.
Als Beispiel nehmen wir einen Gateway 192.168.50.1 mit seinem LAN 192.168.50.0/24. Dieser Gateway habe ein VPN Interface tun0 mit dem Subnetz 10.0.0.0/24, der Gateway selber hat 10.0.0.1 in VPN. Im VPN gibt es einen Client (10.0.0.10) hinter welchem sich ein öffentliches Netz (1.2.3.4/28) befindet. Das Ziel ist es für bestimmte Client im LAN den Traffic für dieses öffentliche Netz durch den VPN Tunnel zu jagen. Für alle anderen Sourcen soll dieser Traffic via default gw raus.
Als erstes müssen wir eine neue Routing Tabelle definieren
1 2 | #/etc/iproute2/rt_tables 1 ovpn |
Die Tabelle heisst also »ovpn» mit einer Metrik von 1
Dann müssen wir dieser Tabelle die entsprechende Firewallmarkierung zuweisen (in diesem Fall 2, Wert ist aber egal)
ip rule add fwmark 2 table ovpn
Dann generieren wir die Firewall Regel welche die Pakete markiert. Hier sollen Pakete des Admin-PC (192.168.50.55) markiert werden. Das LAN Interface ist eth2
iptables -t mangle -A PREROUTING -i eth2 -s 192.168.50.55 -j MARK --set-mark 2
Jetzt sollte auch klar werden wieso »Source Based Routing» nicht ganz korrekt ist. Die Firewall kann ja nach jedem beliebigen Kriterium markieren. Das muss nicht unbedingt etwas mit der Source zu tun haben.
Damit sind wir schon fast fertig, man muss nur noch der Routing Tabelle (ovpn) die passenden Routen hinzufügen
ip route add 1.2.3.4/28 via 10.0.0.10 dev tun0 table ovpn
Das Obige braucht man eigentlich nur dann wenn man dieselbe IP Adresse an mehreren Interfaces hat. Nur dann muss man Pakete über die Firewall mit Markierungen versehen. Wenn jedes Interface eine eigene IP-Adresse hat, kann man sich dies sparen und direkt mit reinem Routing arbeiten. Denn die speziell zu routenden Antwortpakete haben dann mit der IP-Adresse ein eindeutiges Erkennungsmerkmal.
In meinem Fall ist die default Route über 192.168.199.129 im Subnetz 192.168.199.128/25 auf eth1 wo das System die 192.168.199.141 hat. Auf dem zweiten Interface eth0 liegt das Subnetz 192.168.199.0/25. Der Gateway wäre 192.168.199.1 und die IP des Servers 192.168.199.52.
Zuerst generiert man sich die entsprechenden iproute2 Einträge (links steht die Prio und rechts der Tabellenname)
2
3
4
201 eth0
202 eth1
Dann fügt man default Routen für die Tabelle(n) an
2
ip route add default table eth1 via 192.168.199.129 metric 202
Es ist ganz wichtig, dass man zusätzlich noch eine Route für das lokal anliegende Netz macht. Sonst werden Antworten auf Anfragen aus einem bekannten Subnetz an den Gateway geroutet und das wird asymetrisch
2
ip route add 192.168.199.128/25 dev eth1 table eth1 metric 0
Und zum Schluss kommen dann noch die entsprechenden Regeln, welche bestimmte Pakete mit einer Tabelle verknüpfen
2
ip rule add from 192.168.199.141 table eth1 priority 202
Damit werden alle Pakete, welche als Antworten auf Anfragen an die jeweiligen Interfaces generiert werden, auch wieder über dasselbe Interface zurückgeschickt
2
3
4
5
6
7
| | |
| | |
192.168.199.52 eth0 192.168.199.141 eth1 10.66.100.186 eth2
| | |
| | |
------------------------------------- server ----------------------------
Solange der Traffic von einem bekannten Netz (192.168.199.0/25, 192.168.199.128/25 oder 10.66.100.128/25) kommt ist es unproblematisch, weil dies durch die Interface Routen anliegenden Subnetzes gehandhabt wird.
Kommt der Traffic von einem unbekannten Subnetz (10.66.100.0/25), aber über gw3, dann ist das auch kein Problem, weil hier dann die Default Route zum Zuge kommt.
Problematisch wird es erst wenn der Traffic des unbekannten Subnetzes (10.66.100.0/25) via gw1 oder gw2 reinkommt.
Dann würde ohne Source Routing die Default Route zum Tragen kommen und das würde dann asymetrischen Traffic erzeugen.
Natürlich könnte man eine statische Route für das Netz anlegen. Das geht aber nur dann sinnvoll, wenn der Traffic des fraglichen Netzes (10.66.100.0/25) immer via denselben Gateway (z.B. gw2) reinkommt.
Dann würde folgendes reichen
Kann der Traffic aber von allen Gateways kommen geht reines Destination Routing nicht mehr. Denn die statische Route würde wiederum asymetrischen Traffic erzeugen.
Darum braucht man dann Source Based Routing, um sicherzustellen, dass das Ausgangsinterface immer gleich dem Eingangsinterface ist.
Der häufigste Anwendungsfall dafür ist ein System, dass in mehreren Subnetzen beheimatet ist (Multihome)
Damit man diese Regeln automatisch bei Booten laden kann gibt es je nach Distribution unterschiedliche Wege.
Bei Debian basierten Systemen geht es am einfachsten via /etc/network/interfaces
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
post-up ip route add default via 192.168.199.1 table eth0 metric 201
post-up ip route add 192.168.199.0/25 dev eth0 table eth0 metric 0
post-up ip rule add from 192.168.199.52 table eth0 priority 201
iface eth1 inet dhcp
...
post-up ip route add default via 192.168.199.129 table eth1 metric 202
post-up ip route add 192.168.199.128/25 dev eth1 table eth1 metric 0
post-up ip rule add from 192.168.199.141 table eth1 priority 202
iface eth2 inet dhcp
...
post-up ip route add default via 10.66.100.129 table eth2 metric 203
post-up ip route add 10.66.100.128/25 dev eth2 table eth2 metric 0
post-up ip rule add from 10.66.100.186 table eth2 priority 203
Und bei Redhat basierten Systemen
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from 192.168.199.52 table eth0 priority 201
#/etc/sysconfig/network-scripts/rule-eth1
from 192.168.199.141 table eth1 priority 202
#/etc/sysconfig/network-scripts/rule-eth2
from 10.66.100.186 table eth2 priority 203
#/etc/sysconfig/network-scripts/route-eth0
default table eth0 via 192.168.199.1 metric 201
192.168.199.0/25 dev eth0 table eth0 metric 0
#/etc/sysconfig/network-scripts/route-eth1
default table eth1 via 192.168.199.129 metric 202
192.168.199.128/25 dev eth1 table eth1 metric 0
#/etc/sysconfig/network-scripts/route-eth2
default table eth2 via 10.66.100.129 metric 203
10.66.100.128/25 dev eth2 table eth2 metric 0