Projekte/v642/IPv4 Support: Unterschied zwischen den Versionen

Aus FunkFeuer Wiki
< Projekte‎ | v642
Zur Navigation springen Zur Suche springen
(benötigte OpenWRT Pakete)
 
(13 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
Ziel des [[Projekte/v642|v642 Projektes]] ist es das gesamte FunkFeuer Netz auf ein natives IPv6 Netz umzustellen. Genauere Details zu den Beweggründen finden sich auf der Projekt Seite selbst. Es ist allerdings klar das auf absehbare Zeit Endnutzer weiterhin IPv4 Inhalte abrufen werden müssen und diese evt. 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.
Ziel des [[Projekte/v642|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 ==
== Warum 4in6 ==
In der Wikipedia gibt es eine ganze Liste von [https://en.wikipedia.org/wiki/Category:IPv6_transition_technologies|IPv6 transition Mechanismen]. Warum also für uns 4in6?
In der Wikipedia gibt es eine ganze Liste von [https://en.wikipedia.org/wiki/Category:IPv6_transition_technologies 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 das 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 irgendwelche Übersetzungen mit State zentral durchgeführt werden nur schwer möglich. Es wären Port Forwards denkbar aber das ist kurzum alles recht - hmm - Scheisse.
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/Wrapping Mechanismen zur Verfügung. Verwaltung ist für uns hier wichtig da eine grosse Anzahl von Tunnels schwer zu handhaben sind und wir uns das generell ersparen wollen. Daher wollen wir einen Mechanismus der pflegeleicht ist. Auch war uns hier wichtig das wir keinen State in den Tunnels haben. Der Unterschied ist hierbei das ein Tunnel grossteils als konstant gesehen wird - d.h. er hat eine Verbindung welche aufrecht erhalten wird (engl. Stateful). Stateful ist generell schwieriger zu skalieren und für unsere Zwecke ja 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 im Endeffekt aufgrund der gut abgehangenen Spezifizierung (RFC2473[https://www.ietf.org/rfc/rfc2473.txt] im Jahre 1998!) und dem entsprechend guten Support in Linux gewählt wurde.
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 ([https://www.ietf.org/rfc/rfc2473.txt RFC2473] aus dem Jahre 1998!) und dem entsprechend guten Support in Linux gewählt wurde.




== Wie funktioniert 4in6 ==
== Wie funktioniert 4in6? ==
Wenn du 6in4 bereits kennst brauchst du dir das ganze nur genau umgekehrt vorstellen. Daher auch der Name. :)
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 das 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 das jedes Packet das in das Interface gerouted wird in ein IPv6 Packet verpackt wird und das neue Packet mit einer fixen IPv6 Destination und Source Adresse versehen wird. Danach wird das Packet wie jedes andere IPv6 Packet in über das IPv6 Netz geroutet. Am anderen Ende (die Destination Adresse die auf das Packet gegeben wurde) steht dann ein Wrapper Server von uns der das Packet annimmt und das IPv4 Packet da wieder rausholt (das liegt einfach in der IPv6 Packet Payload). Der Wrapper Server hat auch eine native IPv4 Anbindung und dort wird das ausgepackte Packet dann drauf gegeben. In die Rückrichtung geht das ganze einfach umgekehrt - es gibt dafür am Wrapper Server ein entsprechendes Interface das die Packete in die Richtung von deinem Router einpackt und dein Router packt sie aus und schickt sie zum Beispiel in dein Heimnetz. Es gibt noch ein paar spezifische Sachen die der Kernel macht im Bezug auf Fragmentierung, etc. Die sind im RFC entsprechend beschrieben aber für die Grundidee irrelevant.
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.
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 ==
== 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 <code>2a02:60:100:ee::/80</code> announcieren. Da diese Route von mehreren Punkten ins Netz announced wird, wird diese als Anycast verstanden. Anycast heisst das Traffic von euch immer zum topologisch nahsten Server gerouted wird. Auch ermöglicht uns diese Art des Routings sofort Redundanzen zu haben. Wenn ein Server kaputt ist entfernt sich die Route im Netz und der andere Server übernimmt die Arbeit (da kein State besteht ist dies völlig transparent).
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 <code>2a02:61:0:ee::/80</code> 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 wird zu ihnen noch zu fixierende IPv4 Prefixes gerouted. Dort wiederum besteht der Fall das mehrere Routen zur selben IPv4 Adresse führen und diese werden demnach im Backbone Netz zu nahe gelegensten Server gesandt. Selbes Spiel wie oben im Mesh.
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 Austausch von Informationen um eine neue IPv4 Adresse in Betrieb zu nehmen. Der Wrap Server weiss einfach das diese IPv4 Adresse an diesen IPv6 Endpunkt geschickt wird.
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.
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 ===
=== 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[https://www.ietf.org/rfc/rfc4291.txt] näher beschrieben.
Um die Konfiguration dieses Systems einfach zu halten, haben wir uns entschlossen, eine IPv4-in-IPv6-mapped-Struktur zu verwenden. Diese sind im [https://www.ietf.org/rfc/rfc4291.txt RFC4291] näher beschrieben.


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


Daraus ergeben sich folgende verwendbare Adressen:
Daraus ergeben sich folgende verwendbare Adressen:
<blockquote>
<blockquote>
<code>
<code>
2a02:0060:0100:00ee:0000:0000:0000:0000 -
2a02:0061:0000:00ee:0000:0000:0000:0000 -
2a02:0060:0100:00ee:ffff:ffff:ffff:ffff
2a02:0061:0000:00ee:ffff:ffff:ffff:ffff
</code>
</code>
</blockquote>
</blockquote>




Innerhalb dieses Prefixes haben wir zwei /80 zugewiesen welche einmal in die Richtung nach Aussen (Ansicht vom Mesh Endknoten bei dir) und einmal nach Innen routen.
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 Aussen: <code>2a02:60:100:ee::/80</code>
Egress/nach Außen: <code>2a02:61:0:ee::/80</code>
<blockquote>
<blockquote>
<code>
<code>
2a02:0060:0100:00ee:0000:0000:0000:0000 -
2a02:0061:0000:00ee:0000:0000:0000:0000 -
2a02:0060:0100:00ee:0000:ffff:ffff:ffff
2a02:0061:0000:00ee:0000:ffff:ffff:ffff
</code>
</code>
</blockquote>
</blockquote>


Ingress/nach Innen: <code>2a02:60:100:ee:1::/80</code>
Ingress/nach Innen: <code>2a02:61:0:ee:1::/80</code>
<blockquote>
<blockquote>
<code>
<code>
2a02:0060:0100:00ee:0001:0000:0000:0000 -
2a02:0061:0000:00ee:0001:0000:0000:0000 -
2a02:0060:0100:00ee:0001:ffff:ffff:ffff
2a02:0060:0000:00ee:0001:ffff:ffff:ffff
</code>
</code>
</blockquote>
</blockquote>


=== Beispiel Konfiguration ===
=== Beispielkonfiguration ===
Im folgenden eine Beispiel Konfiguration mit welcher die IPv4 Adresse <code>78.41.114.123</code> konfiguriert wird. Der Home Router ist dabei ein Router im Mesh Netz welcher dazu gewählt wurde diese IPv4 Adresse zu terminieren. Dies ist dem Halter der IPv4 Adresse überlassen und kann ein Mesh Router oder ein nachgestellter Router in seinem Netz Perimeter sein.
Im folgenden eine Beispielkonfiguration, mit welcher die IPv4-Adresse <code>185.194.20.123</code> 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 <code>::ffff:123.123.123.123</code>. Um RFC konform zu sein müssen die vorherigen 16 bit mit ffff belegt werden.
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 <code>::ffff:123.123.123.123</code>. 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.


==== Home Router ====
* ip-full
Basierend auf dem Subnet Plan legen wir am Loopback Interface die Endpunkt Adresse für die ankommenden Packete an. Diese wird dann von OLSR in das Mesh Netz announced und dadurch routebar.
* 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.
<blockquote>
<blockquote>
<code>
<code>
ip -6 addr add 2a02:60:100:ee:1:ffff:78.41.114.123/128 dev lo
ip -6 addr add 2a02:61:0:ee:1:ffff:185.194.20.123/128 dev lo preferred_lft 0
</code>
</code>
</blockquote>
</blockquote>
Die Option <code>preferred_lft</code> 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 [http://www.davidc.net/networking/ipv6-source-address-selection-linux 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 den die Source und Destinations wie oben beschrieben an.
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.
<blockquote>
<blockquote>
<code>
<code>
ip -6 tunnel add wrap1 mode ipip6 remote 2a02:60:100:ee::ffff:78.41.114.123 local 2a02:60:100:ee:1:ffff:78.41.114.123 dev lo
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<br/>
ip -6 link set dev wrap1 up
ip -6 link set dev wrap1 up
</code>
</code>
</blockquote>
</blockquote>


Danach muss auf diesem Interface noch die IPv4 Adresse konfiguriert werden.
Danach muss auf diesem Interface noch die IPv4-Adresse konfiguriert werden.
<blockquote>
<blockquote>
<code>
<code>
ip -4 addr add 78.41.114.123/32 dev wrap1
ip -4 addr add 185.194.20.123/32 dev wrap1
</code>
</code>
</blockquote>
</blockquote>


Dies ist die minimale Konfiguration und diese macht diese IPv4 Adresse auf diesem Gerät verfügbar. Jedes Packet das nun in dieses Interface geschickt wird wird im Hintergrund verpackt und weitergesendet auf dem IPv6 Transportnetz. Wenn auf unseren Servern ein Packet für diese 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.
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 <code>wrap1</code> 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 <code>192.168.0.1/24</code>, könnten wir dieses Netz einfach über diese IPv4 Adresse in das Internet NATen. Das ginge dann zum Beispiel so:
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 <code>192.168.0.1/24</code>, könnten wir dieses Netz einfach über öffentliche IPv4-Adresse in das Internet NATen. Das ginge dann zum Beispiel so:
<blockquote>
<blockquote>
<code>
<code>
ip -4 route add 0.0.0.0/0 via 78.41.114.123 dev wrap1
ip -4 route add 0.0.0.0/0 via 185.194.20.123 dev wrap1<br/>
iptables -t nat -A POSTROUTING -o wrap1 -j MASQUERADE
iptables -t nat -A POSTROUTING -o wrap1 -j MASQUERADE
</code>
</code>
</blockquote>
</blockquote>


Wer so ein Setup schon mal mit einer anderen Public IPv4 Adresse gemacht hat wird sehen das das alles genau gleich ausschaut. So wollten wir das eben auch - das für den Endnutzer das weiterhin gleich verwendbar ist.
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 ====
==== 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 für uns vorprovisioniert. Dies ist hier nur dokumentiert falls es jemanden interessiert wie das am anderen Ende ausschaut. Spoiler: sehr ähnlich wie am Home Router.
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 das diese aus dem anderen /80 Netz stammt.
Adresse für die Terminierung am Loopback Interface -- einziger Unterschied, dass diese aus dem anderen /80 Netz stammt.
<blockquote>
<blockquote>
<code>
<code>
ip -6 addr add 2a02:60:100:ee::ffff:78.41.114.123 dev lo
ip -6 addr add 2a02:61:0:ee::ffff:185.194.20.123/128 dev lo preferred_lft 0
</code>
</code>
</blockquote>
</blockquote>
Auch wiederum nur die Adressen umgetauscht und der Interface Name enthält die IPv4 Adresse damit das am Server einfacher zu finden ist.
Auch wiederum nur die Adressen umgetauscht, und der Interface-Name enthält die IPv4-Adresse, damit das am Server einfacher zu finden ist.
<blockquote>
<blockquote>
<code>
<code>
ip -6 tunnel add wrap078041114123 mode ipip6 remote 2a02:60:100:ee:1:ffff:78.41.114.123 local 2a02:60:100:ee::ffff:78.41.114.123 dev lo
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
</code>
</code>
</blockquote>
</blockquote>
Zeile 120: Zeile 126:
<blockquote>
<blockquote>
<code>
<code>
ip -6 link set dev wrap078041114123 up
ip -6 link set dev wrap185194020123 up<br/>
ip -4 route add 78.41.114.123/32 dev wrap078041114123
ip -4 route add 185.194.20.123/32 dev wrap185194020123
</code>
</code>
</blockquote>
</blockquote>


=== Offene Punkte ===
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.
* '''MTUs''' - Auswirkung von geringeren IPv6 MTUs auf grosse IPv4 Packete und Fragmente muss weiter getestet werden.
<blockquote>
<code>
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
</code>
</blockquote>

Aktuelle Version vom 14. September 2019, 21:45 Uhr

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