EdgeRouter mit IPv6

Seit ein paar Jahren habe ich nun einen EdgeRouter X, der mein Heimnetzwerk mit dem Internet verbindet, in Kombination mit DSL-Modem und UniFi-WLAN-Zugangspunkten. Prinzipiell bin ich mit der Anschaffung zufrieden, die eine defekte FritzBox ersetzte, weil der EdgeRouter mehr Flexibilität bietet, allerdings ist er leider eher was für Bastler, denn für normale Anwender. Das betrifft auch IPv6, das von Ubiquity über alle Produktreihen hinweg recht stiefmütterlich behandelt wird, nicht nur beim EdgeRouter, sondern auch beispielsweise bei der UniFi-Serie. Hier also meine Notizen, wie ich IPv6 zum Laufen gebracht habe.

Setup

  • EdgeRouter X mit eigenem DSL-Modem an eth0
  • EdgeOS-Version 2.0.9
  • Zugang über PPPoE (1&1)
  • Der Internetzugang ist schon eingerichtet

Ich habe den Wizard WLAN+2LAN2 ausgeführt und hier schonmal die IPv6-Unterstützung und Prefix Delegation aktiviert. Dadurch entsteht schon mal ein Teil der Konfiguration, aber man kann auch einfach alles wie unten angegeben eintragen.

Basics

Nur nochmal die Grundlagen von IPv6 zum Verständnis:

IPv6-Adressen gibt es für verschiedene Bereiche. Die globalen Adressen sind weltweit gültig, es gibt kein NAT wie bei IPv4. Das bedeutet, dass jedes Gerät eine IPv6-Adresse hat, die es überall verwendet. Webserver im Internet sehen z.B. die IPv6-Adresse eures Handys und nicht die eures Routers. Das ist ein wichtiger Unterschied zu IPv4, weil man z.B. auch bei dynamischem DNS nicht den Router und seine Adresse verwendet.

Ihr erhaltet von eurem Provider beim Verbinden einen Präfix, d.h. eine bestimmte Anzahl von Stellen am Anfang der IPv6-Adresse wird vom Provider vorgegeben. Der Rest wird durch das Gerät selbst festgelegt: Er wird in der Regel aus der MAC-Adresse erzeugt und bleibt auch über verschiedene Präfixe gleich.

Geräte haben oft mehrere IPv6-Adressen, die einen unterschiedlichen Scope haben. Neben den o.g. globalen Adressen, die quasi weltweit eindeutig sind, gibt es noch Link-Local-Adressen, die zur Kommunikation im eigenen Netzwerk dienen und von Routern nicht geroutet werden. Diese beginnen immer mit fe80 und sind nur innerhalb des Netzwerks eindeutig.

Wenn die Privacy Extensions aktiviert sind, wird noch eine weitere, globale Adresse mit dem gleichen Präfix generiert, deren hinterer Teil aber zufällig ist und nicht aus der MAC-Adresse abgeleitet wird. Diese Adresse hat nur einen begrenzten Gültigkeitszeitraum, bevor sie wieder neu erzeugt wird, und verhindert, dass anhand des hinteren Teils immer die gleichen Geräte wiedererkannt werden. Für ausgehende Verbindungen wird dann diese Adresse verwendet, das Gerät ist aber auch unter der „normalen“ IPv6-Adresse erreichbar. Daher sind unter der IPv6-Netzwerkkonfiguration meistens gleich mehrere Adressen aufgelistet.

Verbindet sich eure Internetverbindung neu, bekommen alle Netzwerkgeräte neue (globale) IPv6-Adressen, da sich der Präfix ändert. Der hintere Teil der Adresse bleibt gleich. Das schafft eine zusätzliche Problematik, auf die am Ende des Dokuments eingegangen und die auch gelöst wird.

Konfiguration

Die Konfiguration nehme ich über das Webinterface unter dem Menüpunkt Config Tree vor. Scheinbar ist in der Ubiquity-Community es sehr beliebt, das direkt über die Konsole zu machen, aber so kann man auch gut die Einstellungsmöglichkeiten sehen.

Wenn der Router bereits mit dem WLAN+2LAN2-Wizard konfiguriert wurde, können einige Einstellungen schon da sein.

Internetverbindung

Die grundsätzliche Konfiguration erfolgt unter der PPPoE-Schnittstelle unter interfaces / ethernet / eth0 / pppoe / 0.

  • ipv6 Grundsätzliche IPv6-Unterstützung aktivieren
    • address
      • autoconf aktivieren
    • enable aktivieren
    • dup-addr-detect-transmits auf 1 setzen
  • dhcpv6-pd Prefix Delegation aktivieren (Weitergabe des IPv6-Präfix an das internet Netzwerk)
    • rapid-commit auf enable setzen
    • no-dns aktivieren: IPv6-DNS deaktivieren (falls ihr eigene DNS-Server nutzt)
    • pd
      • 0 hinzufügen
        • prefix-length auf 56 setzen (abhängig von eurem Provider)
        • interface
          • switch0 hinzufügen
            • host-address auf ::1 setzen (Ende der internen IPv6-Adresse für den Router)
            • prefix-id auf :1 setzen
            • service auf slaac setzen
            • no-dns aktivieren
          • Wenn mehrere virtuelle Switches verwendet werden, die auch IPv6 unterstützen sollen, müssen diese mit ihrem entsprechenden Namen (z.B. switch0.2) hinzugefügt werden und je eine eigene host-address und prefix-id erhalten.

Firewall

Die Firewall muss so konfiguriert werden, dass sie IPv6 zulässt. Hier kann ungefähr den Standardkonfiguration des Wizard verwendet werden. Die Konfiguration erfolgt unter firewall / ipv6-name.

  • WANv6_IN hinzufügen
    • default-action: drop
    • description: WAN inbound traffic forwarded to LAN
    • enable-default-log aktivieren
    • rule
      • 10 hinzufügen
        • action: accept
        • description: Allow established/related sessions
        • state
          • established: enable
          • related: enable
      • 20 hinzufügen
        • action: drop
        • description: Drop invalid state
        • state
          • invalid: enable
      • 30 hinzufügen
        • action: accept
        • description: allow ICMPv6
        • protocol: ipv6-icmp
  • WANv6_LOCAL hinzufügen
    • default-action: drop
    • description: WAN inbound traffic to the router
    • enable-default-log aktivieren
    • rule
      • 10 hinzufügen
        • action: accept
        • description: Allow established/related sessions
        • state
          • established: enable
          • related: enable
      • 20 hinzufügen
        • action: drop
        • description: Drop invalid state
        • state
          • invalid: enable
      • 30 hinzufügen
        • action: accept
        • description: allow IPv6 icmp
        • protocol: ipv6-icmp
      • 40 hinzufügen
        Diese Regel war bei mir erforderlich, damit ich auch intern IPv6-Adressen bekomme.
        • action: accept
        • description: Allow IPv6 DHCP
        • protocol: udp
        • destination
          • port: 546
        • source
          • port: 547

Anschließend müssen die Regeln noch unter interfaces / ethernet / eth0 / pppoe / 0 / firewall hinzugefügt werden:

  • in
    • ipv6-name: WANv6_IN
    • unter name sollte bereits die IPv4-Regel WAN_IN stehen
  • local
    • ipv6-name: WANv6_LOCAL
    • unter name sollte bereits die IPv4-Regel WAN_LOCAL stehen

Portfreigaben

Wie oben erwähnt, funktionieren Adressen bei IPv6 anders: Der Zugriff von außen erfolgt direkt über die globale IPv6-Adresse des Geräts, mit dem verbunden werden soll, z.B. dem Webserver. Daher gibt es keine Portweiterleitungen wie bei IPv4, man muss lediglich in der Firewall die Ports für die entsprechenden IPv6-Adressen aufmachen, damit der Traffic durchgelassen wird.

Das erfolgt in der WANv6_IN-Regel unter firewall / ipv6-name / WANv6_IN. Hier einfach noch zusätzliche Regeln unter rule am Ende hinzufügen, die wie folgt aufgebaut sind:

  • action: accept
  • description: z.B. HTTP für Webserver
  • destination
    • address
      Hier die IPv6-Adresse ohne den Präfix angeben und mit Präfix-Maske, ansonsten muss die Adresse nach jedem Reconnect wieder aktualisiert werden, z.B. ::aaaa:bbbb:cccc:dddd/::ffff:ffff:ffff:ffff

Switch

Unter interfaces / switch / switch0 / ipv6 müssen die IPv6-Einstellungen getroffen werden. Wenn ein virtueller Switch genutzt wird, müssen die Einstellungen auch für die entsprechenden virtuellen Switches unter dem Unterpunkt vif getroffen werden.

  • dup-addr-detect-transmits: 1
  • address
    • autoconf aktivieren
  • router-advert Verteilt den Präfix im Netzwerk
    • managed-flag: true
      Notwendig, damit neue Präfixes sofort von den Clients übernommen werden
    • other-config-flag: true
    • prefix
      • ::/64 hinzufügen

Nach diesen Schritten solltet ihr im Idealfall nun IPv6-Adressen mit euren Netzwerkgeräten erhalten. Das könnt ihr mit diversen IPv6-Testseiten prüfen oder einfach mal mit ping6 oder ping -6 irgendeine Domain anpingen, die IPv6 unterstützt.

Adressen-Problematik

Unter den Netzwerkeinstellungen tauchen mit jedem Reconnect immer mehr IPv6-Adressen auf
Unter den Netzwerkeinstellungen tauchen mit jedem Reconnect immer mehr IPv6-Adressen auf

Leider ist die Freude von kurzer Dauer. Wie im Abschnitt Basics beschrieben, erhaltet ihr mit jedem Reconnect einen neuen Präfix und damit eure Netzwerkgeräte neue IPv6-Adressen. Und da entsteht das Problem: Die alten IPv6-Adressen fallen nicht weg und die Netzwerkgeräte versuchen immer noch, die erste erhaltene IPv6-Adresse für die Kommunikation zu nutzen. IPv6-Verbindungen sind dann nicht mehr möglich.

Das Problem ist hier beschrieben und ein Lösungsvorschlag wird gemacht, der jedoch inzwischen nicht mehr so funktioniert.

Router konfigurieren

Von diesem Problem ist zunächst mal euer switch0-Interface bzw. auch die virtuellen Switches am Router betroffen. Daher muss dieser erstmal in der Funktionalität etwas erweitert werden, damit dort die alten IPv6-Adressen gelöscht werden.

Zunächst muss sich per SSH mit dem Router verbunden werden. Unter /config/scripts können eigene Skripte angelegt werden, die auch über Firmware-Updates hinweg erhalten bleiben. Unter /config/scripts/ppp/ip-down.d können Skripte abgelegt werden, die beim Trennen einer PPP-Verbindung ausgeführt werden. Genaugenommen ist dies eine Ergänzung zu den Skripten unter /etc/ppp/ip-down.d. Und hier legen wir nun ein Skript an, das die globalen IPv6-Adressen löscht, wenn die Internetverbindung getrennt wird.

Zunächst den Ordner anlegen, falls er noch nicht existiert:

mkdir -p /config/scripts/ppp/ip-down.d

In den Ordner wechseln und Skript anlegen:

cd /config/scripts/ppp/ip-down.d
vi 9999-remove-v6addr.sh

Wer vi nicht kennt: Mit der I-Taste den Einfüge-Modus aktivieren und anschließend das Skript einfügen:

#!/bin/bash

if [[ "$1" != "pppoe0" ]]; then
    exit 0
fi

DEVICE=switch0

systemctl stop radvd
/sbin/ifconfig "$DEVICE" | grep -E 'inet6.*global' | awk '{print $2 "/" $4}' | while read -r ipv6addr
do
    logger -t "9999-remove-v6addr" "Removing IPv6 address $ipv6addr from $DEVICE"
    ip -6 addr del "$ipv6addr" dev "$DEVICE"
done
systemctl start radvd

Mit ESC wieder den Einfügemodus verlassen und mit :wq die Datei speichern und beenden. Anschließend das Skript noch ausführbar machen mit chmod +x 9999-remove-v6addr.sh.

Virtuelle Switches

Wenn weitere virtuelle Switches mit IPv6-Unterstützung verwendet werden, muss der Teil zwischen systemctl stop und systemctl start dupliziert werden und $DEVICE dann entsprechend durch den virtuellen Switch, z.B. switch0.2 ausgetauscht werden. Wird nur ein virtueller Switch für IPv6 verwendet, kann auch oben einfach der Name in der Variable DEVICE angepasst werden.

Testen

Mit disconnect interface pppoe0 kann nun die Internetverbindung getrennt werden. Der Erfolg kann im System Log des Webinterface oder mit tail -f /var/log/messages betrachtet werden. Da sollte nun so etwas stehen wie:

9999-remove-v6addr: Removing IPv6 address dead:beef:…/64 from switch0

Anschließend mit connect interface pppoe0 die Verbindung wieder herstellen.

Unterschiede zum Skript aus der Quelle
  • Logging hinzugefügt
  • Systemd für radvd nutzen
  • Lokale Adresse wird ignoriert, indem in der Zeile auch nach global gesucht wird, statt fe80 auszuschließen
  • Präfix-Länge wird abgegriffen, da inzwischen notwendig
  • Skript nicht ausführen, wenn Interface nicht pppoe0, da sonst VPN-Verbindungen auch zum Löschen der IPv6-Adressen führen

radvd konfigurieren

Der Dienst, der das Präfix im Netzwerk bekannt gibt, muss noch so konfiguriert werden, dass er alte Präfixe als veraltet markiert. Da die Konfiguration dieses Dienstes immer durch die Routerkonfiguration erzeugt wird und diese leider keine zusätzlichen Optionen zulässt, müssen wir die Erzeugung der Konfiguration anpassen.

Skript anpassen

Achtung: Diese Änderung muss nach jedem Firmware-Update erneut vorgenommen werden.

Per SSH mit dem Router verbinden und die Datei /opt/vyatta/sbin/vyatta_gen_radvd.pl als Superuser öffnen.

sudo vi /opt/vyatta/sbin/vyatta_gen_radvd.pl

Mit der Eingabe von :243 zur Zeile 243 gehen, dort steht folgender Code:

# Write parameters out to config file                          
print $FD_WR "    prefix $prefix {\n";
foreach my $key (keys %prefix_param_hash) {
    print $FD_WR "        $key $prefix_param_hash{$key};\n";
}                                                                
                  
print $FD_WR "    };\n";

Wieder mit der I-Taste in den Einfüge-Modus gehen und an das Ende der foreach-Schleife gehen (die Zeile nur mit }) und anschließend die folgende Zeile einfügen:

print $FD_WR "        DeprecatePrefix on;\n";

Danach kommt dann das bereits vorhandene

print $FD_WR "    };\n";

Mit ESC-Taste und Eingabe von :wq die Änderungen speichern.

Anschließend die Konfiguration neu erzeugen, z.B. indem man den Router neu startet oder die Konfiguration ändert, z.B. unter interfaces / switch / switch0 / ipv6 / router-advert / prefix / ::/64 die valid-lifetime um eine Sekunde ändert (oder gleich mal etwas reduziert).

Testen

Mit cat /etc/radvd.conf kann nun die erzeugte Konfiguration geprüft werden. Hier sollte nun unter dem Präfix die Zeile DeprecatePrefix on; zu finden sein:

prefix ::/64 {
    AdvPreferredLifetime 86400;
    AdvAutonomous on;
    AdvValidLifetime 86400;
    AdvOnLink on;
    DeprecatePrefix on;
};

Prüfen

Nach den beiden Schritten müssen ggf. die Schnittstellen der Netzwerkgeräte noch neu gestartet werden, damit die alten Präfixe verloren gehen. Die Geräte sollten nun wieder IPv6-Verbindung haben, wie man mittels Ping prüfen kann.

Um das dauerhaft korrekte Verhalten zu prüfen, auf den Router per SSH verbinden und die Verbindung neu herstellen:

disconnect interface pppoe0
connect interface pppoe0

Anschließend den Netzwerkgeräten ein bisschen Zeit für die neue IPv6-Adresse geben und wieder den Ping probieren, der nun erfolgreich sein sollte.

Die alten IPv6-Adressen verschwinden nicht sofort aus der Schnittstelle, sondern werden nur als veraltet markiert und bleiben noch einige Zeit erhalten. Dies dient dazu, erreichbar für Geräte zu bleiben, die noch die alte IP-Adresse kennen. Für ausgehende Verbindungen werden aber keine Adressen verwendet, die als veraltet markiert sind. Wie lange die alte Adresse erhalten bleibt, wird mit preferred-lifetime und valid-lifetime in der Konfiguration von router-advert festgelegt. Unter Linux kann man mit ip -6 address sehen, welche Adressen als deprecated markiert sind.