IPv6 mit der Telekom und Archlinux

Da die VDSL-Verbindung nach einer Neustiefelung meines Rechners nicht mehr starten wollte, musste ich mich mal wieder mit diesem Thema auseinandersetzen. Ursache des Ganzen war, dass adsl.service nicht mehr starten wollte, weil /usr/bin/pppoe-start nicht mehr im Paket rp-pppoe enthalten war.

PPPoE

Da immer alles funktioniert hat, ist vollkommen an mir vorbei gegangen, dass pppd mittlerweile ein Plugin bekommen hatte, das PPPoE über das entsprechende Kernel-Modul abwickelt. Scheint so, dass der RP-PPPoE ausgedient hat. Wie auch immer, um eine Verbindung mit der Telekom nur mit pppd herzustellen, erstelle man folgende Konfigurationsdatei in /etc/ppp/peers namens z. B. tkom:

plugin pppoe.so # dafür muss pppoe.ko geladen sein!
tkom # Interface name
name "<kdnr>#0001@t-online.de" # ppp-Benutzername
persist
defaultroute
+ipv6 # Entscheidend für IPv6-Prefix-Delegation!
mru 1380
mtu 1380
hide-password
noauth

Wenn man dann noch das richtige Passwort in /etc/ppp/pap-secrets hinterlegt hat, sollte sich die Verbindung mit systemctl start ppp@tkom aufbauen lassen. @tkom ist der Name der Konfigurationsdatei in /etc/ppp/peers.

Prefix Delegation

Um ein globales IPv6-Prefix für das interne Netz zu bekommen, benötigt man einen DHCPv6-Client, der es an dem PPP-Interface annimmt. Für dhcpcd sieht die Konfiguration so aus:

duid
waitip 6
ipv6only
interface ppp0
ipv6rs
iaid 1
ia_pd 1 int/0/64/801

Die letzten beiden Zeilen sind entscheidend: iaid definiert eine UUID, die dann in ia_pd (das erste Argument, in diesem Fall 1) benutzt wird, um der Netzwerkkarte mit dem Namen int ein /64-Prefix zuzuweisen. Der letzte Parameter ist das Suffix, was das Interface, an das delegiert wird, bekommt, standardmäßig 1, wenn man es auslässt. Aber Wahrschau: Das ist kein String, sondern ein Integer, der in Hexadezimal umgewandelt wird (801 == 0x321)!

Router Announcements

Um das LAN am IPv6-Leben teilhaben zu lassen, muss das IPv6-Netz auch verkündet werden, und zwar mit radvd. Um dessen Konfiguration auf Stand zu halten, gibt es den Hook /usr/lib/dhcpcd/dhcpcd-hooks/40-delegate, der /usr/local/sbin/delegate_prefix.sh aufruft, wenn es ein neues Prefix gibt. Dieses Skript schreibt eine Konfiguration mit dem neuen Prefix und startet den Trümmer neu.

DHCP

Für DNS, DHCPv4 und DHCPv6 ist dnsmasq zuständig. IPv4-DHCP ist so trivial, dass ich es nicht erklären muss.

DHCPv6 leider komplizierter. Zunächst muss man radvd mit der Option AdvManagedFlag on sagen, dass die Clients überhaupt danach fragen. Wie statische IPv6-Adressen vergeben werden, hängt von dem dem Client ab. ArchLinux mit networkd macht das recht einfach. Man muss lediglich Token=::c0a0:808 in der Sektion [IPv6AccetRA] eintragen, um ebendieses Suffix zu bekommen.

Windows hingegen fragt nach einer DUID via DHCP-SOLICIT oder INFORM. Bei dem entsprechenden dhcp-host= Eintrag beachten, dass ein vorangestelltes id: einen literalen String bedeutet. Um einen Windows-Client zu beglücken, lasse man sich die DUID via ipconfig /all ausgeben, ersetze '-' durch ':' und verteile dann eine IP ohne 'id:' nach dem Gleichheitszeichen.

Networking with Hetzner

Setting the scene

Recently I found out the hard way that Hetzner frowns upon MAC addresses on their switch ports they don’t know, so they blocked my server.

What happened: The wan interface was a member of the bridge connecting my virtual machines, because from what I knew back then that was the only way to provide the VMs with IPv6 addresses from the Hetzner subnet. So their MAC addresses (52:54:…) went out to the switch. This was so bad that they didn’t even allow me to unlock it temporarily to fix the problem!

What I did: Reboot the server via the robot to shut down. They aren’t started automatically on boot. Then notify Hetzner via the robot that I fixed the problem by reconfiguring the network configuration. They replied very quickly by checking for foreign MAC addresses and, since they found none, unlocked my server. Now I had a chance to reconfigure the network without using their hardware KVM.

The fix

First thing to do, was remove the wan interface from the bridge. That was a remnant from a completely bridged setup from long ago, anyway. Since all IP4 traffic was routed, that wasn’t a problem. IPv6 was a problem, though. The router announcements from radvd worked, but neighbor discovery didn’t, so the VMs didn’t have IPv6 connectivity.

I finally found this article: It boils down to:

  • Give the wan interface a single IPv6 address from your assigned network (netmask /128) to make it a part of it.
  • Assign the bridge the same address, only with a /64 netmask!

The article does it for Debian. Translated to systemd-networkd I ended up with this:

The wan interface

/etc/systemd/network/wan.network

[Match] 
Name=wan <- The interface name is set by an udev rule

[Network] 
Address=2001:db8::2/128 <- /128 is the clue!!!
Gateway=<replace.with.ipv4.gateway>
Gateway=fe80::1 <- This is literal!!!

[Address] 
Address=<your.ipv4.address>
Peer=<the.peer>/32

Create the bridge

[NetDev] 
Name=br0 
Kind=bridge

Do not attach the wan interface to the bridge!

Configure the bridge

[Match] 
Name=br0 

[Network] 
Address=192.168.0.1/24 <- Your private IPv4 VM network
Address=2001:db8::2/64 <- YES, this is the same address as wan!

Don’t be alarmed if br0 is not configured and down on reboot. Once you start a VM using the bridge it will be taken up and have all the right addresses. If you add the IPv6 address manually with ip, you will loose IPv6 connectivity, since the kernel creates a useless default route! You have been warned!

Works like a charm (for now)!

IPv6 mit der Telekom, Linux und pppoe

Pflicht: IPv4-Konnektivität

Wie das geht, habe ich hier beschrieben. Wenn das nicht läuft, geht auch nichts mit IPv6.

Kür: IPv6-Konnektivität

Ist eigentlich ganz einfach, wenn man weiß, dass Forwarding für das ppp-Interface ausgeschaltet sein muss. Ansonsten kann man lange auf ein Prefix warten: Man bekommt zwar eins, aber das Interface wird nicht konfiguriert!

So geht dem:

Unter Arch Linux gibt es die Datei /etc/ppp/ipv6-up.d/00-iface-config.sh. Dort trägt man Folgendes ein:

#!/bin/bash
echo 1 > /proc/sys/net/ipv6/conf/$1/use_tempaddr 
echo 0 > /proc/sys/net/ipv6/conf/$1/forwarding 
echo 1 > /proc/sys/net/ipv6/conf/$1/autoconf 
echo 1 > /proc/sys/net/ipv6/conf/$1/accept_ra

Wichtig ist die 2. Zeile: forwarding == 0, wie schon oben erwähnt. Diese Option ist der Schlüssel zum Glück, wirklich!

use_tempaddr kann ganz nach Gusto gesetzt werden, und autoconf muss natürlich auch aktiviert sein. Bei accept_ra bin ich mir nicht sicher.

Als Nächstes braucht man rdisc6 (Arch Linux: pacman -S ndisc6). Dann legt man eine neue Datei in /etc/ppp/ip-up.d an (Name egal, Hauptsache, es ist ein ausführbares Shell-Script). Bei mir heißt sie tkom-up.sh:

#!/bin/bash
rdisc6 ${IFNAME}

${IFNAME} wird von dem PPP-Gerümpel gesetzt und enthält den Namen des PPP-Interfaces (Überraschung!).

Zu guter Letzt muss man dem PPP-Dämonen noch sagen, dass er auch für IPv6 zuständig ist. Dafür fügt man die Zeile

+ipv6

irgendwo in /etc/ppp/options hinzu. Nach einem beherzten

# systemctl restart adsl

sollte eine globale IPv6-Adresse an ppp* rangeflanscht sein!

Ansonsten wäre da noch…

systemd-networkd, das standardmäßig Router-Announcements an IPv4-Only-Interfaces entgegennimmt und eine nervige Default-Route via fe80::1 setzt. Das kann man dem Trum abgewöhnen, indem man IPv6AcceptRA=false zu der .network-Unit hinzufügt. Bei mir sieht das so aus (ehemals KD, jetzt Vodafone-Verbimmelung):

[Match] 
Name=ext 
 
[Network] 
DHCP=v4 
IPv6AcceptRA=false