Wenn zwei unterschiedliche Netzwerke die gleiche IP Range haben…

Vorweg: mit IPv6 wäre das nicht notwendig. IPv6 ist aber immer noch nicht flächendeckend ausgerollt (und wird es wohl zu meiner Lebenzeit auch nicht)

Wenn man sich via VPN aus einem beliebigen Netz in sein eigenes Netzwerk verbindet funktioniert das nur, wenn das Lokale Netz (aus dem man sich verbinden will) eine andere Netzmaske hat, als das Zielnetz, in das man sich verbinden will.

In meinem Fall Hotel-WLan-Gateway die gleiche Adresse wie eine meiner Server (auf dessen Service ich gerade zugreifen wollte).

Ich halte ja mittlerweile zwei unterschiedliche VPN Netzwerk Konfigurationen bereit, für den Fall, dass mein Gastnetzwerk den gleichen Addressraum nutzt, denn auch mein VPN hat. Für die Zieladressen konnte ich diesen Weg aber nicht gehen.

Das Problem kann man mit einem Router und „Policy Based Routing“ lösen.

Der Router wird mit dem zur Verfügung gestellten Gast Netz verbunden (IP Range A) und stellt selber ein Netzwerk (IP Range B) zur Verfügung. Der Router wählt sich nun in das VPN-Netzwerk ein (IP Range C). Das interne Netzwerk, dass durch das VPN erreicht werden soll, hat auch IP Range A.

Das Problem: wenn ein Client aus IP Range B versucht auf interne Ressourcen mit der IP Range A zuzugreifen, geht der Router nicht über das VPN, sondern auf den direkten Link, also ins GastNetz.

Die Lösung: man legt sich eine neue Routing Table an, die zwei Einträge hat:

Den Lokalen Link für das eigene Netzwerk (IP Range B)
eine Default Route über das VPN (IP Range C)

Das kann dann so aussehen

ip route add IP-RANGE-B dev LOCAL-DEV proto kernel scope link src LOCAL-IP table 200 
ip route add default via VPN-GW-IP dev VPN-DEV table 200

Anschließend muss man dem Router nur noch dazu Bringen, alles aus dem eigenen Netzwerk (IP Range B) über diese Tabelle zu routen. Das geht wie folgt:

ip rule add from IP-RANGE-B lookup 200

Wenn nun etwas aus dem eigenen Netzwerk (IP Range B) bearbeitet wird, kennt der Router das GastNetz (IP Range A) nicht.

Das ganze kann man auch ohne Router erreichen, also mit einem Client direkt im GastNetz (IP Range A) und einer OpenVPN Instanz am laufen. Dann werden die „ip rule“ Statements nur viel komplizierter.

Die Ansatz hier ist: Sämtlichen Traffic, der nicht von dem VPN erzeugt wird, über eine gesonderte RoutingTable zu bearbeiten und nur den VPN Traffic an das Default GW zu bekommen. Der Kniff ist „Sämtlichen Traffic, der nicht von dem VPN erzeugt wird“ korrekt zu erkennen. Möglichkeiten hier sind:

  • Alles was nicht an den Default GW gesendet wird
  • Alles was nicht von einem bestimmten User erzeugt wurde

Alles in allem hat man einfach ein bisschen mehr Aufwand.

Oder man sorgt mittels IPv6 einfach dafür, dass man keine zwei Netze mit gleicher IP Range hat…

Routing unter Ubuntu

Einen Text mit viel „Bla-Bla“ hatte ich heute schon, jetzt gibt es Technisches!

Will man unter Ubuntu einen „echten“ Router betreiben, also dynamisch auf die Netzwerkumgebung reagieren, stehen zwei Routing-Suites zur Verfügung: BIRD und Quagga. Beide unterstützen die wichtigsten Routing-Protokolle: BGP, RIP, OSPF

Wichtiger Hinweis vorweg: in Ubuntu 10.04 wird BIRD noch in Version 1.1.5 ausgeliefert. Die ist mal gut zwei Jahre alt und Unterstützt noch nicht alle Funktionen. Entweder akzeptiert man diese Schwächen oder nutzt das PPA des CZ.NIC Labs.

Die Quagga-Suite ist schon seit einiger Zeit am Markt. Sie bietet ein Config-Interface das einem CISCO Router gleicht. Man kann sowohl Config Files hinterlegen als auch „on the fly“ Config Befehle geben und die entsprechende Config dann raus schreiben (ganz wie bei CISCO Routern). Im Hintergrund werden bei Quagga für jedes Routing-Prokoll ein eigener Dienst gestartet und jeder dieser Dienste macht einen TELNET Port auf. Diesen kann man auf den Localhost beschränken oder so konfigurieren, dass er jede Anfrage ablehnt (kein Password angeben).

Bird befindet sich aktuell noch in der (Weiter-)Entwicklung. Zudem wirkt es auf mich schlanker. Es wird nur ein Dienst gestartet, die Config befindet sich in einer Datei und wirkt übersichtlicher. Neben diesen „Geschmacksfragen“ soll BIRD leistungsschonender sein.[1. Quelle: Vergleich BIRD/Quagga] Laut Wiki kommt er vor allem deswegen in den großen „Verteilerknoten“ zum Einsatz. [2. Quelle: Wikipedia] Dafür spricht auf jeden Fall, dass bei DD-WRT Firmwares für wenig Speicher der BIRD zum Einsatz kommt und bei viel Speicher die Quagga-Suite.

Ich habe beide Implementierungen gezwungenermaßen durch meine Routern im Einsatz. Beim Ubuntu-Router hatte ich die Wahl und mich nach einem kleinen Quagga Test für BIRD entschieden.

Wichtig: Die meisten Routing-Protokolle nutzten MultiCast-Addressen für ihre Kommunikation. Damit das funktioniert muss man eine entsprechende Route hinterlegen.

route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0

Beispiel – Konfiguration BIRD

Einfach über apt-get oder aptitude bird installieren und schon kann es losgehen.

aptitude install bird

Danach kann man die /etc/bird.conf bearbeiten.

log syslog all;
router id 10.1.0.1;

protocol kernel {
        export all;
        learn;
}

protocol device {
        scan time 60;
}

protocol ospf {
        debug { states, routes, interfaces };
        area 0 {
                interface "eth0" 10.1.0.0/16 {
                        cost 10;
                        stub;
                        check link;
                };
                interface "eth1" 10.2.0.0/16 {
                        priority 10;
                        cost 100;
                        type broadcast;
                        hello 30; retransmit 5; wait 10; dead 120;
                        authentication none;
                        check link;
                };
                interface "eth2" 10.3.0.0/16 {
                        priority 10;
                        cost 10;
                        type broadcast;
                        hello 30; retransmit 5; wait 10; dead 120;
                        authentication none;
                        check link;
                };
        };
}

Die Config dürfte selbsterklärend sein. Ein paar Hinweise zum Umgang mit BIRD:

  • Das Kernel-Protokoll wird gebraucht. Ohne die „export all;“ Regel werden keine Routen an das OS bekanntgegeben.
  • Hat man Default-Routen oder pflegt händisch welche über den „route“-Befehl nach, sollte die über das „learn“-Statement von BIRD ermittelt werden.
  • Alle lokalen Netze, die den Nachbarn mitgeteilt werden sollen, benötigen ein interface-Statement. Das stub-Statement markiert Interfaces die nur „announced“ werden sollen aber sonst keine Funktion haben.
  • Wenn man einen PPPoE-DSL-Uplink als Default-Route verwendet, sollte man das PPPoE Interface nicht als Area-Interface hinterlegen.
  • „check link“ funktioniert nur, wenn man neuerere BIRD-Versionen benutzt. BIRD 1.1.5 meckert einen Syntax-Fehler an.

 Beispiel – Konfiguration Quagga

Installation:

aptitude install quagga

Quagga ist anfangs etwas komplizierter. Anfangs muss man erst mal die benötigten Dienste unter /etc/quagga/daemons freischalten. Will man, dass diese Dienste per TelNet auch Remote konfigurierbar sind muss man noch in der /etc/quagga/debian.conf Anpassungen vornehmen.

Auf jeden Fall benötigt man den zebra-Dienst. Dieser ist das „protocol kernel“ Pendant. Zusätzlich muss man noch den Dienst für das gewünschte Protokoll aktivieren. Für den einfachen Einstieg findet man Beispiel-Konfigurationen unter /usr/share/doc/quagga/examples.

zebra.conf

hostname deadend-router

interface br0
  link-detect
interface ath1
   link-detect

in der zerba.conf werden die zu nutzenden interfaces angegeben.

ospf.conf

interface br0
  ip ospf cost 10
  ip ospf dead-interval 120
  ip ospf hello-interval 30
  ip ospf retransmit-interval 5
  ip ospf network broadcast
interface eth0
  ip ospf cost 10
  ip ospf dead-interval 120
  ip ospf hello-interval 30
  ip ospf retransmit-interval 5
  ip ospf network broadcast

router ospf
  ospf router-id 10.3.0.10
  network 10.3.0.0/16 area 0
  network 10.4.0.0/16 area 0
    redistribute kernel
    redistribute connected

In der ospf.conf wird diesen Interfaces erst Eigenschaften zugewiesen und anschließend das Protokoll zugeschaltet. Wichtig ist die Syntax. Das Einrücken dient nur zur Optik und hat kein Einfluss. Die Reihenfolge der Befehle hingegen hat Einfluss. Gewisse Befehle „öffnen“ eine SubConfig-Ebene. Ein „ip ospf cost“ ist nur gültig, wenn vorher eine interface-Direktive stand. Was bei den „interface“-Direktiven noch übersichtlich erscheint, kann bei den area-direktiven unübersichtlich werden, da diese ineinander geschachtelt sein können. Angenehm sind hingegen die redistribute -Direktiven. So muss man nur die Interfaces auflisten, auf den auch wirklich ein weiterer Router lauscht.