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.

Custom kernel build

Turns out that building a custom kernel for ArchLinux isn’t as easy as it seems. Just changing $pkgver in the official PKGBUILD doesn’t work, because it doesn’t fetch the sources from the official git tree, but from a clone on github. Here’s how to do it as of 2021-07-31:

  1. Change pkgbase to e.g. linux-ryzen
  2. Change pkgver to the version you want to compile

Then change the sources array to:

"$_srcname::git+https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git#tag=v${pkgver}"

This will clone the stable source tree HEAD. To checkout a specific version, add the following to prepare() after cd $_srcname:

echo "Checking out $_srctag"
git checkout "v${pkgver}"

If you want to save some time, remove make htmldocs from build() and the equivalent from pkgname() at the bottom.

Share and enjoy!

Valhalla NIC

As it seems, the NIC in current valhalla has a hardware bug, causing hardware unit hangs. To work around this, disable scatter-gather, TCP segmentation offloading and generic receive offload with this command:

# ethtool -K wan sg off tso off gro off

I did that 11 days ago, and didn’t get a single unit hang yet. Keep your fingers crossed!

Dual boot with UEFI

Install Windows first. The setup creates an EFI partition, most likely as /dev/sd?2. We’re gonna need that later. Then turn off fast boot. Enter

powercfg -h off

on the command prompt. Make sure that you have local admin rights. Fast boot is incompatible with dual boot. You’ll get blue screens with repair options otherwise. While at it, set the system clock to UTC. Create this DWORD registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\RealTimeIsUniversal

and set it to “1”.

Then install linux and mount /dev/sd?2 from above to boot. Then create a new file named arch.conf in /boot/loader/entries:

title   Arch Linux
linux   /vmlinuz-linux
initrd  /initramfs-linux.img
options root=UUID=$(blkid /root/partition) rw audit=0

The paths are relative to /boot, so vmlinuz-linux should be /boot/vmlinuz-linux. Next edit /boot/loader/loader.conf:

console-mode auto
default arch
timeout 5

Assuming that you’re using systemd-boot, run bootctl install and bootctl update, reboot and be happy!

Synergy and SDDM

For SDDM to connect to a synergy server on archlinux, edit /usr/share/sddm/scripts/Xsetup and add:

/usr/bin/synergyc <server IP or server hostname>

There’s just a little problem if you have more than one monitor. The default Xorg config mirrors all screens. That’s no problem, since KDE sets it all up properly. Unfortunately synergyc doesn’t register the changes, so you have to restart it. Since by then synergyc is running as root, you can’t kill it as user. But fear not, there’s a workaround:

  • Allow the user to execute /usr/bin/killall synergyc as root without password (see https://tollana.d-tor.org/notes-to-self/?p=620)
  • Kill all synergy instances in an autostart script and start a user instance preferably in the systemd user session:
#!/bin/bash 
sudo /usr/bin/killall synergyc
systemctl --user restart synergyc
  • make it executable, put it somewhere the user can access it and auto-start it. In KDE: System Settings -> Startup and Shutdown -> Autostart -> Script File
  • make sure that you have synergyc.service in $HOME/.config/systemd/user
[Unit]
Description=Synergy Client Daemon
After=network.target

[Service]
ExecStart=/usr/bin/synergyc --no-daemon <Server IP or Hostname>
Restart=always
RestartSec=3

[Install]
WantedBy=default.target

This works with KillUserProcesses=yes in /etc/systemd/logind.conf.

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)!

Bold font in KDE konsole

To get a bold font in Konsole, do this:

  • First, create a new Profil
  • Edit the profile to use DejaVu Sans Mono, Size and Style doesn’t matter
  • Save it and close Konsole
  • Edit $HOME/.local/share/konsole/<Profile Name>
  • Add or replace the Font Entry under Appearance with
Font=DejaVu Sans Mono,9,-1,0,75,0,0,0,0,0,Bold
  • Now edit $HOME/.config/konsolerc and add
[Desktop Entry] 
DefaultProfile=<Profile Name>
  • Replace [Favorite Profiles] with
[Favorite Profiles] 
Favorites=

Kill all instances of Konsole, start it and never touch that stuff again!

Archlinux and an AMD-GPU

I finally decided to get rid of my ancient nvidia graphic board and bought a Sapphire Radeon R5 230 with 2GB RAM for 46,40 €uros. The vendor chose GLS as delivery service, so no tracking number. Of course it didn’t arrive at the announced day. I had to ask the vendor and eventually picked it up in a not so close boutique.

Well, once I had it, assembly wasn’t much of a problem. Configuring X was. Took me five hours to get it right!

First, I had to figure out which driver to use, which isn’t as easy as it seems. Turns out to be radeon, not amdgpu. Without any configuration the radeon kernel module is loaded, which is right, by the way, but X can’t figure out what driver to use. By default it uses amdgpu if installed. Well, wrong choice.

Create a configuration with

# X -configure

and change the Driver from amdgpu to radeon. Then remove the vnc module in Section “Module” and the Screens in Section “ServerLayout”. X identifies 2 Devices, one for VGA output, and one for DVI, or so I thought. Actually, the card has another output: HDMI for TV-out, which happens to be the default. Very clever! Disable it by adding this to the kernel command line:

video=HDMI-A-1:d

Now set the option ZaphodHeads to “VGA-0,DVI-0” in both device Sections. That should get you up and running. SDDM still doesn’t work, but startx will. SDDM requires some xrandr magic in Xsetup, which I haven’t figured out yet.

Anyway, it was worth it! No more annoying delays when playing videos while writing text in LibreOffice! In total the system feels much faster now.

You can marvel at the whole config here.

DDNS with bind and perl

Problem

You have a crappy internet provider who hands out dynamic IPv4 addresses and IPv6 prefixes, but you can’t remember all those numbers and want to use DNS as intended. Actually, I have 2 internet providers, Vodafone and Telekom, each with its own problems . Vodafone’s IPv6 prefix seems to be static for now, but they blessed me with DS-Lite after the update to 400 Mbit. Telekom has a dual stack, but the public IPv4 address and the delegated IPv6 prefixes are highly dynamic.

What you need

  1. A DNS zone and control over the zone file, so you can delegate a subdomain to another name server
  2. The “another name server” with a static IP. If you don’t have that, stop reading!
  3. a script for the dynamic updates

I have a root server and a DNS zone at Hetzner. The root Server has a static IPv4 address and IPv6 prefix. Also, they let you edit the pure bind zone file via a text box, not a form! Since I’m a perl guy, I did the script in my favorite perfect and easy readable language.

Configure your “another name server”

Install bind on your box with the static IP. Then generate a key for dynamic updates. Do not use dnssec-keygen as described in various tutorials. You will fail! Use ddns-confgen instead and follow the instructions in the comment. Your zone file should look something like this:

...
// THE key
key "ddns-key.dyn.d-tor.org" { 
       algorithm hmac-sha256; 
       secret "base64stufffromddns-confgen="; 
};
// THE dynamic zone
zone "dyn.d-tor.org." { 
       update-policy { grant ddns-key.dyn.d-tor.org zonesub ANY; }; 
       type master; 
       file "dyn.d-tor.org.hosts"; 
};
...

The above snippet configures the zone dyn.d-tor.org and allows updates to anyone who has THE key. Next, create the initial zone file in the directory specified by the “directory” directive in named.conf (on ArchLinux it’s the default /var/named, thus /var/name/dyn.d-tor.org.hosts):

$ORIGIN . 
$TTL 600        ; 10 minutes 
dyn.d-tor.org           IN SOA  valhalla.d-tor.org. me.d-tor.org. ( 
  1          ; serial 
  500        ; refresh (8 minutes 20 seconds) 
  500        ; retry (8 minutes 20 seconds) 
  86400      ; expire (1 day) 
  500        ; minimum (8 minutes 20 seconds) 
) 
  NS      valhalla.d-tor.org.

Then restart/reconfigure bind and check for errors:

# systemctl restart named
# journalctl -u named

If you have ip(6)tables running, allow access to port 53 UDP and TCP for good measure:

# iptables -I INPUT 2 -p udp --dport 53 -j ACCEPT
# iptables -I INPUT 2 -p tcp --dport 53 -j ACCEPT
# iptables -I INPUT 2 -p udp --dport 53 -j ACCEPT
# iptables -I INPUT 2 -p tcp --dport 53 -j ACCEPT

Copy the key to the box where you want to update from, e.g. /etc/ddns.key and set permissions to 600. It should contain only the key section:

key "ddns-key.dyn.d-tor.org" { 
       algorithm hmac-sha256; 
       secret "base64stufffromddns-confgen="; 
};

Now test it:

# nsupdate -k /etc/ddns.key <<EOF
> server 2a02:4f8:2a:254e::2
> update delete blub.dyn.d-tor.org A
> update add blub.dyn.d-tor.org 200 A 191.139.50.71
> send
> EOF

If you’ve done everything right:

# host blub.dyn.d-tor.org 2a02:4f8:2a:254e::2
blub.dyn.d-tor.org has address 191.139.50.71

Delegate the Zone

Now we need to delegate dyn.d-tor.org to 2a02:4f8:2a:254e::2. Add this to the zone file on your authoritative name server (in my case, Hetzner):

...
dyn IN NS dyndns ; delegation to dyndns.d-tor.org
dyndns IN AAAA 2a02:4f8:2a:254e::2 ; IPv6 glue record for dyndns.d-tor.org
dyndns IN A <IPv4.address.of.dyndns> ; IPv4 glue record
...

Wait for the information to spread. Check with dnstracer:

# dnstracer -s . dyn.d-tor.org

If you get a result, we can continue 🙂

THE script

Write a script that extracts the IP addresses from your interfaces and uses nsupdate to update the records. It shouldn’t be that hard. Sorry, I can’t provide mine, because it is very specific to my setup.