Projekte/v642/IPv4 Support

Aus FunkFeuer Wiki
< Projekte‎ | v642
Wechseln zu: Navigation, Suche

Ziel des v642-Projektes ist es, das gesamte FunkFeuer-Netz auf ein natives IPv6-Netz umzustellen. Genauere Details zu den Beweggründen finden sich auf der Projektseite selbst. Es ist allerdings klar, dass auf absehbare Zeit Endnutzer weiterhin Inhalte über IPv4 abrufen werden und diese eventuell auch bereitstellen wollen. Um dies zu ermöglichen, gibt es eine Vielzahl an sogenannten Transition-Mechanismen. Im Folgenden sollen die Gründe, warum wir uns für 4in6 als den Mechanismus für das FunkFeuer-Netz entschieden haben, und auch die technische Implementierung erläutert werden.


Warum 4in6

In der Wikipedia gibt es eine ganze Liste von IPv6-Transition-Mechanismen. Warum also für uns 4in6?

Als ersten Schritt nahmen wir alle Mechanismen aus dem Rennen, welche dem Endnutzer keine IPv4-Adresse in seinem Netzwerk-Perimeter zur Verfügung stellen. Wir hielten es für wichtig, dass in einem freien Netz die Nutzer weiterhin auf beiden Netzwerk-Protokollen Inhalte nach ihren eigenen Wünschen verbreiten können. Dies wäre mit NAT-basierten Lösungen, wo Protokollübersetzungen mit State zentral durchgeführt werden, nur schwer möglich.

Am Ende bleiben uns damit noch einige Tunnel- und Wrapping-Mechanismen zur Verfügung. Verwaltung ist für uns hier wichtig, da eine große Anzahl von Tunnels schwer zu handhaben sind und wir uns das generell ersparen wollen. Daher wollen wir einen Mechanismus, der pflegeleicht ist. Auch soll State in den Tunnels vermieden werden. Der Unterschied ist hierbei, dass ein Tunnel großteils als konstant gesehen wird -- das heißt er hat eine Verbindung, welche aufrecht erhalten wird (engl. Stateful). Stateful ist generell schwieriger zu skalieren und für unsere Zwecke irrelevant da wir nur zwischen zwei Protokollen übersetzen wollen. Damit begeben wir uns auf das Feld, das besser als Wrapper oder Übersetzer zu bezeichnen ist. Hier kommt dann auch 4in6 ins Spiel, welches aufgrund der gut "abgehangenen" Spezifizierung (RFC2473 aus dem Jahre 1998!) und dem entsprechend guten Support in Linux gewählt wurde.


Wie funktioniert 4in6?

Wenn du 6in4 bereits kennst, brauchst du dir das ganze nur genau umgekehrt vorstellen. Daher auch der Name. :)

Im ganz einfachen Sinne kann man sich das so vorstellen, dass auf einem Router z.B. bei Dir daheim eine 4in6-Terminierung konfiguriert wurde. In dieser Konfiguration wird ein virtuelles Interface erstellt, das so konfiguriert ist, dass jedes IPv4-Paket, das in das Interface gerouted wird, in ein IPv6-Paket verpackt wird, und das neue Paket mit einer fixen IPv6-Destination- und -Source-Adresse versehen wird. Danach wird das Paket wie jedes andere IPv6-Paket über das IPv6-Netz geroutet. Am anderen Ende (das ist die Destination-Adresse, die das Paket bekommen hat) steht dann ein Wrapper-Server von uns, der das Paket annimmt und das IPv4-Paket wieder aus der Payload des IPv6-Pakets rausholt. Der Wrapper-Server hat auch eine native IPv4-Anbindung, und dort wird das ausgepackte IPv4-Paket dann ausgegeben. In die Rückrichtung geht das ganze einfach umgekehrt -- es gibt dafür am Wrapper-Server ein entsprechendes Interface, das die IPv4-Pakete in die Richtung von Deinem Router in IPv6-Pakete einpackt; Dein Router packt die IPv4-Pakete wieder aus und schickt sie zum Beispiel in Dein Heimnetz. Es gibt noch ein paar spezifische Sachen, die der Kernel macht (in Bezug auf Fragmentierung, etc.). Die sind im RFC entsprechend beschrieben, aber für die Grundidee irrelevant.

Wenn Du noch mehr dazu wissen willst, such am besten nach 6in4 (da gibts mehr Content dazu), und denk Dir das ganze einfach im umgekehrten Falle.


Implementierung

Im Netz werden vom Verein an den Border-Punkten (im Moment bei Nessus und in der Krypta) sogennannte Wrapping-Server zur Verfügung gestellt. Diese Server werden im IPv6-Mesh die Route 2a02:61:0:ee::/80 announcieren. Da diese Route von mehreren Punkten ins Netz announciert wird, wird diese als Anycast verstanden. Anycast heißt, dass Traffic von Euch immer zum topologisch nächsten Server geroutet wird. Auch ermöglicht uns diese Art des Routings sofort Redundanzen zu haben. Wenn ein Server kaputt ist, wird die Route im Netz nicht mehr announciert, und ein andere Server übernimmt die Arbeit. Da (anders als bei Tunnellösungen) kein State besteht, ist das Wechseln auf einen anderen Wrapping-Server völlig transparent.

Weiters haben diese Server native IPv4-Anbindung am Backbone-Netz. Über diese Anbindung werden zu ihnen noch zu fixierende IPv4-Prefixes geroutet. Dort wiederum besteht der Fall, dass mehrere Routen zur selben IPv4-Adresse führen, und diese werden demnach im Backbone-Netz zum nächstgelegenen Server gesandt. Selbes Spiel wie oben im Mesh.

Auf jedem Server werden alle IPv4-Adressen aus den Netzen, die wir dorthin routen, vorkonfiguriert. Dies ist möglich, da wir ein statisches Mapping der IPv4-Adresse in die IPv6-Endpunkt-Adresse machen. Dadurch benötigt es keinerlei neue Konfiguration, um eine IPv4-Adresse in Betrieb zu nehmen, wenn sie Dir zugewiesen wurde. Der Wrap-Server weiß einfach, dass diese IPv4-Adresse an diesen IPv6-Endpunkt geschickt wird.

Auf der anderen Seite bei Dir wiederum konfigurierst Du nur ein solches Interface für die IPv4-Adresse die Dir zugewiesen wurde. Die IPv6-Adressen, die Du für diese Konfiguration benötigst, ergeben sich wiederum aus der Dir zugewiesenen IPv4-Adresse. Mehr dazu im Beispiel unten.


Subnet-Plan

Um die Konfiguration dieses Systems einfach zu halten, haben wir uns entschlossen, eine IPv4-in-IPv6-mapped-Struktur zu verwenden. Diese sind im RFC4291 näher beschrieben.

Für die Wrapper-Infrastruktur wurde der folgende Prefix zugewiesen: 2a02:61:0:ee::/64

Daraus ergeben sich folgende verwendbare Adressen:

2a02:0061:0000:00ee:0000:0000:0000:0000 - 2a02:0061:0000:00ee:ffff:ffff:ffff:ffff


Innerhalb dieses Prefixes haben wir zwei /80 zugewiesen, welche einmal in die Richtung nach Außen (also ins Internet aus Sicht vom Mesh-Endknoten bei Dir) und einmal nach Innen routen.

Egress/nach Außen: 2a02:61:0:ee::/80

2a02:0061:0000:00ee:0000:0000:0000:0000 - 2a02:0061:0000:00ee:0000:ffff:ffff:ffff

Ingress/nach Innen: 2a02:61:0:ee:1::/80

2a02:0061:0000:00ee:0001:0000:0000:0000 - 2a02:0060:0000:00ee:0001:ffff:ffff:ffff

Beispielkonfiguration

Im folgenden eine Beispielkonfiguration, mit welcher die IPv4-Adresse 185.194.20.123 konfiguriert wird. Der Home-Router ist dabei ein Router im Mesh-Netz, welcher dazu gewählt wurde, diese IPv4-Adresse zu terminieren. (Welcher Router das in der Praxis macht, bleibt aber dem Halter der IPv4-Adresse überlassen: Es kann ein Mesh-Router oder ein nachgestellter Router in seinem Netz-Perimeter sein.)

Notiz am Rande. In den meisten Betriebssystemen, die IPv6 unterstützen, können IPv4-mapped-Adressen einfach eingegeben werden, indem diese als letzte 32 Bit der Adresse in Dotted-Decimal-Notation eingegeben werden. Zum Beispiel ::ffff:123.123.123.123. Um RFC-konform zu sein müssen die vorherigen 16 Bit mit ffff belegt werden.

OpenWRT

OpenWRT benötigt folgende Pakete um die Befehle in den nächsten Abschnitten ausführen zu können.

  • ip-full
  • kmod-ip6-tunnel

Home-Router

Basierend auf dem Subnet-Plan legen wir am Loopback-Interface die Endpunktadresse für die ankommenden Pakete an. Diese wird dann von OLSR in das Mesh-Netz announciert und dadurch routebar.

ip -6 addr add 2a02:61:0:ee:1:ffff:185.194.20.123/128 dev lo preferred_lft 0

Die Option preferred_lft setzen wir, damit diese Adresse nicht anstatt der Loopback-Adresse für Verbindungen, die von diesem Router ausgehen (und keine spezifische Source-IP haben), verwendet wird. Mehr Details hierzu gibt es hier -- leider kann man in Linux keine Primary-IPv6-Adresse für ausgehende Verbindungen setzen.

Als nächstes legen wir ein virtuelles Interface mit 4in6-Konfiguration an und aktivieren dieses. Die IPv6-Adressen geben die Source und Destinations wie oben beschrieben an.

ip -6 tunnel add wrap1 mode ipip6 remote 2a02:61:0:ee::ffff:185.194.20.123 local 2a02:61:0:ee:1:ffff:185.194.20.123 dev lo
ip -6 link set dev wrap1 up

Danach muss auf diesem Interface noch die IPv4-Adresse konfiguriert werden.

ip -4 addr add 185.194.20.123/32 dev wrap1

Dies ist die minimale Konfiguration. Sie macht diese IPv4-Adresse auf diesem Gerät verfügbar. Jedes Paket, das nun in dieses Interface geschickt wird, wird im Hintergrund verpackt und auf dem IPv6-Transportnetz weitergesendet. Wenn auf unseren Servern ein Paket für diese IPv4-Adresse ankommt, wird das dann umgekehrt gemacht, und wenn es auf der IPv6-Adresse, die am Loopback-Interface konfiguriert wurde, ankommt, wird es ausgepackt und auf dem wrap1 Interface ausgegeben.

Da dies nun ein Interface wie alle anderen im Linux-Kernel ist, kann es für lokales NAT, Port Forwarding, etc. genutzt werden. Wenn auf diesem Router zum Beispiel noch ein anderes Interface mit Deinem internen IPv4-Netz ist -- sagen wir 192.168.0.1/24, könnten wir dieses Netz einfach über öffentliche IPv4-Adresse in das Internet NATen. Das ginge dann zum Beispiel so:

ip -4 route add 0.0.0.0/0 via 185.194.20.123 dev wrap1
iptables -t nat -A POSTROUTING -o wrap1 -j MASQUERADE

Wer so ein Setup schon mal mit einer anderen Public-IPv4-Adresse gemacht hat, wird sehen, dass das alles genau gleich ausschaut. So wollten wir das eben auch -- dass das für den Endnutzer weiterhin gleich verwendbar ist.


Wrap-Server

Die folgende Konfiguration wird für jede IPv4-Adresse, die wir für den Transition-Mechanismus zuweisen, auf unseren Wrap-Servern vorhanden sein. Diese muss nicht angelegt werden, wenn eine neue IPv4-Adresse zugewiesen wird, sondern wird von uns vorprovisioniert. Dies ist hier nur dokumentiert, falls es jemanden interessiert, wie das am anderen Ende ausschaut. Spoiler: sehr ähnlich wie am Home Router.

Adresse für die Terminierung am Loopback Interface -- einziger Unterschied, dass diese aus dem anderen /80 Netz stammt.

ip -6 addr add 2a02:61:0:ee::ffff:185.194.20.123/128 dev lo preferred_lft 0

Auch wiederum nur die Adressen umgetauscht, und der Interface-Name enthält die IPv4-Adresse, damit das am Server einfacher zu finden ist.

ip -6 tunnel add wrap185194020123 mode ipip6 remote 2a02:61:0:ee:1:ffff:185.194.20.123 local 2a02:61:0:ee::ffff:185.194.20.123 dev lo

Gleich wie auch oben.

ip -6 link set dev wrap185194020123 up
ip -4 route add 185.194.20.123/32 dev wrap185194020123

Da es leider Systeme gibt die ICMP Nachrichten filtern und daher keine PMTU (Path MTU) Discovery durchführen können, verwenden wir TCP MSS Clamping auf dem Wrap Server. Dadurch werden die initialen TCP SYN Messages angepasst damit sie die korrekte MTU verwenden.

iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu