Archive

Kategorien

Policy Based Routing

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

3 comments to Policy Based Routing

  • Tobi

    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)

    1
    2
    3
    4
    #/etc/iproute2/rt_tables

    201    eth0
    202    eth1

    Dann fügt man default Routen für die Tabelle(n) an

    1
    2
    ip route add default table eth0 via 192.168.199.1 metric 201
    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

    1
    2
    ip route add 192.168.199.0/25 dev eth0 table eth0 metric 0
    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

    1
    2
    ip rule add from 192.168.199.52 table eth0 priority 201
    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

    • Tobi
      1
      2
      3
      4
      5
      6
      7
                      gw1 (192.168.199.1)                    gw2 (192.168.199.129)          gw3 (10.66.100.129 def Router)
                              |                                       |                               |
                              |                                       |                               |
                      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

      1
      ip route add -net 10.66.100.0/25 via 192.168.199.129

      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)

    • Tobi

      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

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      iface eth0 inet dhcp
       ...
       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

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      #/etc/sysconfig/network-scripts/rule-eth0
      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

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">

  

  

  

4 × 2 =

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahren Sie mehr darüber, wie Ihre Kommentardaten verarbeitet werden .