Router Advertisements mit radvd unter Arch Linux einrichten und nutzen

Bild: Icon Router Advertisement Damon In diesem Kapitel wollen wir uns eingehender mit der Thematik Router Advertisements zusammen mit dem Daemon radvd unter Arch Linux beschäftigen.

Das Thema Router Advertisement ist unter anderem im RFC 4861 - Neighbor Discovery in IPv6 definiert. Hosts und Router verwenden dieses Protokoll, um z.B. die Link-Layer-Adressen für Nachbarn zu ermitteln oder auch zwischengespeicherte Werte von ungültigen Verbindungen wieder zu löschen. Für Hosts ist dieses Neighbor Discovery Protokoll auch wichtig um benachbarte Router zu finden und auch herauszufinden, welche Variante bei der IP-v6-Adresszuweisung benutzt werden soll, SLAAC oder DHCPv6.

Der Router Advertisement Daemon (radvd) implementiert das Ankündigen (Advertisement) von link-local IPv6-Adressen und IPv6_Präfixen mit Hilfe des Neighbor Discovery für IP Version 6 (IPv6) - RFC 2461.

Bevor wir uns nun aber mit der Installation und Konfiguration unseres Router Advertisement Daemon beschäftigen, werden wir noch kurz einen Blick auf die grundlegende Idee und Theorie dahinter. Verbindet sich ein Client mit einem IPv6-Netzwerk benötigt er diverse Informationen, wie z.B.:

  • Welche IP-Adressen habe ich bzw. werde ich haben, wie z.B. Global Unified Adress (GUA), oder habe ich auch noch eine Unique Local Address (ULA) und wie komme ich an diese oder woher beziehe ich diese?
  • Gibt es Router und wie erreiche ich diese und ist dieses Routing statisch oder dynamisch?
  • Gibt es Dinge wie Time- oder DNS-Server?
  • Muss ich bei der Suche spezielle DNA-Suchreichenfolgen bzw. -listen beachten?

Bei einer statischen Konfiguration, z.B. mit Hilfe von Ansible konfiguriert, werden all diese Parameter i.d.R. mit Hilfe von Konfigurationsdateien bekannt gegeben. Bei dynamischen sich oft ändernden Geräten/Clients wird dies praktikabel nicht mehr möglich sein. Wir brauchen also eine andere Art und Weise, wie wir all die Daten den Clients zur Verfügung stellen können. Hier bedienen wir uns den Router Advertisement um die Informationen zu verteilen.

Das Router Discovery Protokoll ermöglicht es Clients/Hosts Router im Netz zu erkennen und alle relevante Routing-Informationen zu bekommen.

  • Router senden von sich aus regelmässig per SOLICITED ROUTER ADVERTISEMENTS (Multicast) an alle Clients im eigenen Netz.
  • Verbindet sich ein Host mit dem Netzwerk, kann er eine Router Solicitation (RS)-Nachricht an die Router per Multicast senden.
  • Der oder die Router im Netzwerk antworten auf die RS-Nachricht ihrerseits mit einer Router Advertisement (RA)-Nachrichten.
  • RA-Nachrichten enthalten alle wichtige Informationen wie die Standard-Gateway-Adresse, Präfix-Informationen so wie andere/weitere Konfigurationsoptionen.
  • Der Host wertet diese RA-Nachrichten aus um so an die Adresse des Default-Routers zu gelangen, seine eigenen Netzwerkparameter entsprechend den Vorgaben zu setzen oder ggf. einen DHCPv6 Server zu befragen um an diese Konfigurationsoptionen zu gelangen.

Nachfolgendes Schaubild fasst den grundlegenden Ablauf zusammen:

erfolgreiche Ablauf aus Sicht des Clients bei der Kommunikation mit dem RADV-/DHCPv6-Servers  RADV - SERVER/DAEMON  RADV - SERVER/DAEMON  Client / Host  Client / Host  DHCPv6 - SERVER/DAEMON  DHCPv6 - SERVER/DAEMON (Port 547) ROUTER SOLICITATION1. Der Hosts erkundigt sich mit einerRouter Solicitation-Nachrichtennach Routern auf einerangeschlossenen Verbindung.UNSOLICATED ROUTER ADVERTISEMENTS (Port 546)2. Der Router gibt seine Anwesenheitzusammen mit verschiedenen Verbindungs-und Internet-Parametern als Antwort auf eineRouter-Solicitation-Nachricht bekannt.(Port 547) SOLICIT an alle Router/DHCPv6 Server3. Der Host fordert mit dieser NachrichtRouter Advertisements sofort undnicht erst zum nächsten geplantenZeitpunkt zu senden.SOLICITED ROUTER ADVERTISEMENTS (Port 546)4. Der Router sendet gezielt an den anfragendenHost die zugehörigen Verbindungs- und Inter-net-Parameter.REQUEST bzw. INFORMATION REQUEST Unicast (Port 547)5. Im Falle von SLAAC erfolgt dieAushandlung der IPv6-Adressenmit den anderen Hosts im Netzvom Client aus. Im Falle von DHCPv6 frägtder Client beim betreffendenDHCPv6-Server nach der IP-Adresse und ggf. weiterenParametern wie DNS oderSearch-Listen.(Port 546) Antwort mit REQUESTED INFORMATION Unicast6. Bei DHCPv6 antwortet der Serverund teilt dem Client die ange-forderten Parameter mit.

Hinweis.: Das Neighbor Discovery Protocol basiert auf ICMPv6-Nachrichten und nutzt die beiden UDP-Ports 546 und 547. Router Advertisement (RA ) Typ 134 und auch Router Solicitation (RS) Typ 133 sind wesentliche Bestandteile des Neighbor Discovery Protocol. Router Solicitation (RS) und Router Advertisement (RA) Messages sind in RFC 4861 definiert.

RS — Router Solicitation (ICMPv6 type 133)

Mit Hilfe von Router Solicitation Nachrichten versucht ein Client Router im Netzwerk zu finden. So kann dieser bei einer Antwort direkt mit der Konfiguration seines Netzwerks fortfahren und muss nicht warten bis der Router selbst per multicast eine entsprechende Router Advertisement Nachricht verschickt. Bei einer Router Solicitation Nachricht handelt sich um eine ICMPv6-Nachricht, die an die All-Router-Multicast-Adresse (ff02::2) gesendet wird.

  • Hosts erfragen mit Hilfe von RS-Nachrichten, ob ein Routern im Netzwerk verfügbar ist.
  • Auf RS-Nachrichten antworten Router mit einer RA-Nachrichten und liefern so wichtige Informationen zur Netzwerkseitigen Konfiguration.

RA — Router Advertisement (ICMPv6 type 134)

Router Advertisment Nachrichten werden vom Server entweder regelmässig an alle Clients im Netz oder ebnen speziell auf An Anfrage durch einen Client versandt. Es handelt sich also im ersten Fall um eine ICMPv6-Nachricht, die an die All-Nodes-Multicast-Adresse (ff02::1) oder eben als Unicast-Nachricht an einen bestimmten Host gesendet wird.

  • Ein Router verwenden diese RA-Nachrichten, um seine Anwesenheit, Netzwerkparameter und weitere Konfigurationsoptionen für Hosts bekannt zu geben.
  • Hosts verwerten diese RA-Nachrichten, um daraus z.B. den Default-Router, den bzw. die Netzwerk-Präfixe, die Link-MTU oder ob z.B. ein DHCPv6-Server im Netz verfügbar ist, sowie weitere relevante Netzwerkinformationen abzuleiten.
    Ist ein DHCPv6-Server verfügbar ist, wird dies durch zwei Flags in der Router-Ankündigung angezeigt. Diese Flags sind das Konfigurationsflag für die verwaltete Adresse und das andere Konfigurationsflag. Das M-Bit und das O-Bit werden verwendet, um diese Flaggen zu setzen. Das M-Bit zeigt an, dass DHCPv6-Dienste für Adress- und Konfigurationseinstellungen verfügbar sind. Das O-Bit zeigt an, ob andere Konfigurationsparameter als die IP-Adresse über den DHCPv6-Dienst verfügbar sind. RAs bestehen also aus bestimmten Flags und Optionen (Präfix, MTU, DNS, SLLA - Src Link-Layer Address). Die wichtigsten Optionen sind hierbei:
    • Address Autoconfiguration A-Flag : Eine '1' bedeutet, dass der Host seine eigene IPv6-Adresse mittels SLAAC erstellt.
    • Home-Agent H-Flag: Dieses Flag wird verwendet, um anzuzeigen, dass es sich bei dem beworbenen Präfix um ein Heimnetzwerk-Präfix handelt, insbesondere für Mobile IPv6, dass sie also somit als Home Agent für Mobile IPv6 fungieren und Dienste für mobile Knoten bereitstellen können.
    • On-link L-Flag: Ist dieses Flag gesetzt, wird definiert dass ein bestimmtes Präfix als „on-link“ betrachtet wird, d.h. dass Hosts Adressen innerhalb dieses Präfixes verwenden können, um direkt mit anderen Hosts auf demselben Link zu kommunizieren. Ist das L-Flag nicht gesetzt, müssen Hosts einen Router verwenden um Hosts in diesem Präfix erreichen zu können.
    • Managed M-Flag : Eine '1' bedeutet, dass die Adresse durch stateful DHCPv6 bereitgestellt wird.
    • Other O-Flag : Eine '1' bedeutet, dass die Adresse von Stateless DHCPv6 bereitgestellt wird, was für die Bereitstellung von Optionen nützlich ist, wenn der Client SLAAC-StatelessAddress Autoconfiguration durchführt.
    • Router-Präferenz (Prf): Der Wert in diesem Feld steht für die Präferenzstufe des Routers, der die RA-Nachricht sendet. So wird z.B. darüber ermittelt ob das Gateway als Standardgateway fungieren soll. Das Prf-Feld kann drei Werte annehmen: Hoch (0x00), Mittel (0x40) oder Niedrig (0x80). Router mit einem höheren Präferenzwert werden gegenüber Routern mit niedrigeren Werten bevorzugt.

Der Router Advertisement Daemon radvd wird auf Linux-Systemen häufig dort ausgeführt, die als IPv6-Router fungieren. Dieser sendet in regelmässigen Abständen bzw. auch auf Anforderung eines Hosts/Clients, sofern dieser eine Router-Solicitation-Nachricht gesendet hatte, Router-Advertisement-Nachrichten gemäss RFC 2461 an ein lokales Ethernet-LAN.

Das Projekt selbst ist in einem Git-Repo auf GitHub geführt.

Die Installation des IPv6 Router Advertisement Daemon (radvd) erfolgt unter Arch Linux mit dem Paket radvd aus dem Extra Repository

Die Installation erfolgt einfach unter Arch Linux mit Hilfe des Paketmanagers pacman.

 # pacman -S radvd

bzw.

 $ sudo pacman -S radvd

Bei Bedarf können wir uns hier gezielt informieren woher das Paket kommt und was es beinhaltet.

 # pacman -Qil radvd

Paketinhalt und -info des Pakets radvd

Firewall/Paketfilter - firewalld

Bevor wir nun unseren radvd Konfigurieren und starten müssen wir natürlich sicherstellen, dass auf dem betreffendem Host auch die Kommunikationsbeziehungen entsprechend erlaubt sind.

Wie auch schon früher bei CentOS ab Release 7 bzw. den nachfolgenden Relaese-Kandidaten Stream von RHEL nutzen wir auch unter Arch Linux den dynamischen firewalld Service. Ein grosser Vorteil der dynamischen Paketfilterregeln ist unter anderem, dass zur Aktivierung der neuen Firewall-Regel(n) nicht der Daemon durchgestartet werden muss und somit alle aktiven Verbindungen kurz getrennt werden. Sondern unsere Änderungen können on-the-fly aktiviert oder auch wieder deaktiviert werden.

In folgendem Konfigurationsbeispiel gehen wir von einem Host aus, der zwei Firewall-Zonen hält, einmal die Zone idmz und einmal die Zone intra. Nur in der Zone intra soll später der radvd seine Router Advertisement Nachrichten verschicken bzw. auf entsprechende Anfragen antworten.

Damit unsere Clients Verbindungen zu dem geöffneten dhcpv6-client-Port 546/udp und dhcpv6-server-Port 547/udp unseres radvd-Daemons aufbauen können, müssen wir für diese noch Änderungen am Paketfilter firewalld vornehmen.

Mit Hilfe des Programms firewall-cmd legen wir nun eine permanente Regel in der Zone intra an. Genug der Vorrede, mit nachfolgendem Befehl werden die Ports für den Service dhcpv6 geöffnet.

 # firewall-cmd --permanent --zone=intra --add-service=dhcpv6
success 

Anschliessend können wir den Firewall-Daemon einmal neu laden und überprüfen, ob die Regeln auch entsprechend unserer Definition, gezogen haben.

 # firewall-cmd --reload
success

Werfen wir noch kurz einen Blick in die Zone intra:

# firewall-cmd –zone=intra –list-services

dhcpv6

automatischer Start des Daemon

Damit der Daemon radvd automatisch bei jedem Systemstart startet, kann die Einrichtung eines Start-Scriptes über folgenden Befehl erreicht werden:

 # systemctl enable radvd.service
 Created symlink '/etc/systemd/system/multi-user.target.wants/radvd.service' → '/usr/lib/systemd/system/radvd.service'.

Ein Überprüfung ob der Dienst (Daemon) radvd wirklich bei jedem Systemstart automatisch mit gestartet wird, kann durch folgenden Befehl erreicht werden:

 # systemctl is-enabled radvd.service
 enabled

Starten werden wir den radvd-Daemon erst einmal noch nicht, da wir diesen ja noch konfigurieren müssen. Nachfolgend werden wir noch detailliert zu einzelnen Anwendungsfällen eingehen:

Was ist SLAAC und wie funktioniert es

Bevor wir uns nun mit der Konfiguration unseres radvd beschäftigen, machen wir erst einmal klar, was SLAAC ist und wie es funktioniert. Jeder IPv6-Host in unserem Netz benötigt eine weltweit eindeutige Adresse, damit dieser auch ausserhalb dessen lokalen Segments kommunizieren zu können.

SLAAC1) ist von der Grundidee her ein einfacher und unkomplizierter Ansatz für die IPv6-Autoadressierung. SLAAC wird im RFC 4862 beschrieben. In seiner aktuellen Implementierung, wie sie in RFC 4862 definiert ist, stellt SLAAC den Hosts keine DNS-Serveradressen zur Verfügung, weshalb es derzeit noch nicht allzu weit verbreitet ist. Dennoch kann SLAAC eine Option sein, wenn Host in unserem Netz diese, ohne einen Separaten Server/Dienst der verwaltet welcher Knoten welche IPv6-Adresse nun hat, diese ihre eigene IPv6-Adressen selbst automatisch konfigurieren sollen. Daher nennt man diesen Mechanismus auch zustandslose Adress-Autokonfiguration. SLAAC stellt jedoch keine DNS-Informationen bereit! Wobei ein hier von der Theorie her, in den Router Advertisement ein eigenen Header der dieses Problem künftig mal lösen können sollte. Eine weitere Herausforderung bei SLAAC ist das Thema DAD2). Wie bereits angemerkt gibt es keine übergeordnete Instanz, die die Vergabe der IPv6-Adressen überwacht, sprich es gibt keinen Server der verfolgt, welche Adressen bereits zugewiesen wurden und welche Adressen noch für eine Zuweisung verfügbar sind. Daher müssen die Knoten selbst, eigenständig und eigenverantwortlich alle doppelten Adresskonflikte nach folgender Logik aufzulösen:

  1. Generieren der eigenen LLA3)
  2. Ausführen der DAD
    • dabei jeweils Auswerten des DAD-Ergebnisses:
      • ist dieses positiv, die erzeugte IPv6-Adresse bereits in Verwendung zurück zum Punkt Erzeugen einer IPv6-Adresse…
      • ist dieses negativ, die erzeugte IPv6-Adresse ist noch nicht in Verwendung, SLAAC ist erfolgreich und die IPv6-Adresse kann benutzt werden.
  3. Senden einer RS4) Nachricht in das Netzsegment
  4. Erzeugen einer ULA5) bzw. GUA6)-IPv6-Adresse
  5. Ausführen der DAD
    • dabei jeweils Auswerten des DAD-Ergebnisses:
      • ist dieses positiv, die erzeugte IPv6-Adresse bereits in Verwendung zurück zum Punkt Erzeugen einer IPv6-Adresse…
      • ist dieses negativ, die erzeugte IPv6-Adresse ist noch nicht in Verwendung, SLAAC ist erfolgreich und die IPv6-Adresse kann benutzt werden.

Werfen wir nun noch einen Blick auf die einzelnen Schritte:

  1. Der Host generiert sich selbst eine LLA (Link Local Address)   :
    Verbindet sich ein Host mit unserem IPv6-Netzwerk, konfiguriert sich dieser zunächst eine Link Local Address. Dies ist notwendig, da der Host für alle weiteren Schritte auf Layer 3 mit den anderen Hosts im gleichen Netzwerksegment in Verbindung treten zu können. Hierzu wird aller Voraussicht nach sofern der Client sich an RFC 3927 hält, aus der Kombination Link Lokal Prefix FE80::/64 und der EUI-64-Schnittstellenkennung, welche er aus der MAC-Adresse der Netzwerkkarte/WLAN-Adapter generiert, eine entsprechende Adresse erzeugen.
    Benutzen wir z.B unter Arch Linux auf unserem Client-Host den NetworkMangers können wir uns die generierte LLA wie folgt anzeigen lassen ip addr show <-linkname-> | grep scope\ link Im Falle des Netzwerkadapters enp0s25 wäre das dann:
     # ip addr show enp0s25 | grep scope\ link
         inet6 fe80::fa4e:fbee:c806:f070/64 scope link noprefixroute

    Die generierte DUID können wir uns wie folgt anzeigen lassen nmcli connection show <-linkname-> | grep dhcp6_client_id. Im Falle unseres Netzwerkadapters mit dem Namen enp0s25 wäre das dann:

     # nmcli connection show enp0s25 | grep dhcp6_client_id
    DHCP6.OPTION[1]:                        dhcp6_client_id = 00:04:80:6f:6d:f5:a6:44:99:a4:3f:9f:09:7c:69:8d:e8:d2


  2. Der Host führt eine DDA (Duplicate Address Detection) durch   :
    Unter Aufgabe 1 haben wir gesehen, dass sich der Clienthost selbst eine Link Local Address generiert hat. Theoretisch könnte es nun passieren, dass warum auch immer ein Host sich eine LLA gegeben hat, die bereits schon in Verwendung ist. Er muss also selbst sicherstellen, dass seine LLA im lokalen Netzwerk eindeutig und noch nicht in Verwendung ist, auch wenn die Wahrscheinlichkeit dass das passieren könnte durchaus sehr gering ist, aber ausgeschlossen kann dies def. nicht werden!! Der Host muss also eine DAD anstossen.
    Im RFC 4429 - Optimistic Duplicate Address Detection (DAD) for IPv6 ist genau beschrieben, was DAS ist und wie es funktioniert. Grundlegend kann man festhalten, dass jeder Host einer Multicast-Gruppe beitritt, welche durch Adresse FF02::1:FFnn:nnnn identifiziert wird, wobei nn.nnnn die letzten sechs hexadezimalen Werte der IPv6-Unicast-Adresse entspricht, egal ob nun dies eine GUA oder eine ULA ist. Aus diesem Grund tritt der Host nun automatisch jeder generierten Solicited-Node-Multicast-Gruppe bei, egal ob es sich um eine link-lokale oder globale IPv6-Adresse handelt. Dieser Vorgang wird als Duplicate Address Detection (DAD) bezeichnet und wird bei jeder neuen Adresszuweisung durchgeführt.

  3. Der Host sendet eine RS (Router Solicitation) Nachricht in das Netzsegment   :
    Damit SLAAC ordnungsgemäss funktionieren kann, ist es notwendig, dass die beiden ersten Schritte erfolgreich abgearbeitet worden sind. Ohne Erfolgreiche Generierung einer LLA und anschliessender DAD dieser erzeugten Adresse, kann nicht weiter fortgefahren werden, auch wenn diese beiden Funktionen nicht direkt Teil der Stateless Autoconfiguration-Funktion sind, denn ohne eine gültige link-local-Adresse kann der neue Host nicht auf Layer 3 mit allen anderen IPv6-Knoten im selben Netzwerk-Segment kommunizieren.
    Der neue Host sendet zunächst eine ICMPv6-Nachricht, genauer gesagt eine Router Solicitation (RS) in das Netzwerksegment und frägt somit alle IPv6-Router, die an dieses Segment angeschlossen sind, nach dem verwendeten globalen Unicast-Präfix. Als Zieladresse verwendet er dabei FF02::2 und Quell-IP-Adresse benutzt er seine zuvor generierte LLA. Nur Router, die selbst auch der Multicast-Gruppe FF02::2 zugehörig sind, werden auf die empfangene outer Solicitation-Nachricht mit einer ICMPv6-Nachricht namens Router Advertisement (RA) antworten. Diese RA-Nachricht enthält das globale IPv6-Präfix auf dem Link und sowie die Präfixlänge. Bei der Quell-IPv6-Adresse verwendet dann der Router eine eigene link-lokale Adresse und als Ziel die All-Nodes-Multicast-Adresse FF02::1. Aktuell gibt es noch keine Möglichkeit DNA-Informationen in dem RA-ICMPv6-Paket mitzuschicken und so dem Client bekannt zu geben, obgleich theoretisch hierzu ein Feld in der RA-Nachricht existiert.

  4. Der Host generiert seine GUA (Global Unicast Address)   :
    Sobald der neue Host die Router Advertisement ICMPv6-NAchricht vom Router empfangen hat, kann der Host nun mit dem erhaltenen Präfix und seiner eigenen EUI-64-Schnittstellenkennung seine Global Unified Address (GUA) bzw, seine Unified Local Address (ULA) generieren, je nachdem welchen Präfix erhalten hat. Die Default-Route zu dieser gerade eben erzeugten IPv6-Adresse kann der Client-Host entsprechend setzen, die diese entweder in der RA-Nachricht explizit gesetzt wurde oder falls dies nicht der FAll war, an Hand der link-lokale Adresse des Routers der die RA-Meldung versandt hatte. Der SLAAC-Prozess ist aber noch nicht abgeschlossen, denn auch hier muss der Client mit Hilfe einer DAD sicherstellen, dass seine automatisch generierte Adresse im lokalen Segment eindeutig ist!

  5. Der Host führt eine DAD (Duplicate Address Detection) durch : Wie auch schon bei Schritt 2 führt der Client-Host nun die erforderliche DAD-Überprüfung durch, damit sichergestellt ist, dass seine selbst generierte Adresse eindeutig ist!

Unique Local IPv6 prefix

Nachdem wir uns nun eingehend mit den Grundlagen und Hintergründen zu SLAAC auseinander gesetzt haben, machen wir uns nun noch an die Konfiguration unseres radvd. Bevor wir zu Tat schreiten gehen wir noch speziell auf ein ganz besonderes Thema ein, nämlich dem unique local IPv6 prefix so wie dies im RFC 4193 definiert wurde.

IPv6-Unique-Local-Adressen (ULAs) werden ähnlich wie die IPv4-Local-Adressen 192.168.0.0/16 verwendet, wie wir diese aus der früheren IPv4-only Welt kannten, kurz Private IP-Adresse genannt. IPv4-Privatadressen wurden durch RFC 1918 definiert, während IPv6-ULAs durch RFC 4193 festgelegt wurden. Im Gegensatz zu ihrem IPv4-Gegenstück haben IPv6-Lokaladressen einen 40-Bit-Zufallsanteil, der sie eindeutig macht. Ziel der lokalen IPv6-Adressen ist es, dass bei einer Verbindung zweier privater IPv6-Netze/Lokationen, die über VPN verbunden sind, Adresskonflikte mit hoher Wahrscheinlichkeit ausgeschlossen werden können.

Die empfohlene Methode zur Erzeugung einer globalen ID ist im RFC 4193 , Abschnitt 3.2.2 definiert:

  1. Bestimmen der aktuellen Uhrzeit.
  2. Beschaffung einer eindeutigen Systemkennung, z.B. einer EUI-64, einer MAC-Adresse oder Generierung einer einigermassen zufälligen Zahl.
  3. Durch die Verkettung der beiden vorgenannten Werte, wie Uhrzeit und Zufallszahl wird ein eindeutiger Schlüssel generiert.
  4. Anschliessend wird ein SHA1-Digest des generierten Schlüssels berechnet.
  5. Aus den letzten 40 Bit des ermittelten SHA1-Digest wird als globale ID verwendet.

Das Ganze brauchen wir natürlich nicht manuell durchführen, sondern wir bedienen uns hierzu des ULA-Generators von cd34. Bei unserem Konfigurationsbeispiel gehen wir mal davon aus, dass uns fdb6:cb48:9d77:0::/64 als unique local IPv6 prefix vorgeschlagen wurde.

SLAAC Konfiguration beim radvd

Bei der Installation des Paketes radvd aus dem extra-Repository von ArchLinux ist eine default Konfigurationsdatei /etc/radvd.conf dabei. Diese sichern wir uns jedoch und beginnen von the scratch mit unserer eigenen individuellen Konfigurationsdatei.

 #  cp -a /etc/radvd.conf /etc/radvd.conf.orig

Im Abschnitt Grundlagen haben wir u.a. im Kapitel RA — Router Advertisement (ICMPv6 type 134) gelernt, dass mit Hilfe von diversen Flags definiert werden kann, wie den Clients mitgeteilt werden kann, welche Art und Weise bei der IPv6-Zuweisung beschritten werden soll.

Bei unserem Konfigurationsbeispiel hier gehen wir für den Router Advertisement Daemon radvd für die Adressvergabe über SLAAC von folgenden Eckwerten aus:

  • Netzwerkinterface :
    Der radvd soll nure auf dem Netzwerkinterface eth1 operieren, also dort lauscht er auf Router Solicitation ICMPv6-Nachrichten neuer Klients und beantwortet selbige mit Router Advertisements ICMPv6-Nachrichten bzw. sendet auf dieser Netzwerkschnittstelle regelmäßig seine Router Advertisements ICMPv6-Nachrichten an alle Clients im lokalen betreffenden Netz.
  • M-Flag:
    AdvManagedFlag = off (Adresskonfiguration über SLAAC)
  • O-Flag:
    AdvOtherConfigFlag = on (Abrufen einer DNS-Serverliste und einen Domain-Namen von einem Stateless DHCPv6-Server, aber keine keine Adressierungsinformationen.
  • A-Flag: \\AdvAutonomous = on (Adresskonfiguration über SLAAC)
  • Global-Scope Address Prefix :
    2001:a:bcd:1234
    • Route :
      2001:a:bcd:1234::/64 und eine Gültigkeit von einer 1/2 Stunde, also 1800 Sekunden.
  • Unique Local IPv6 prefix :
    Hier verwenden wir den zuvor erzeugten Prefix von fdb6:cb48:9d77:0::/64.
    • Route :
      fdb6:cb48:9d77:0::/64 ebenfalls eine Gültigkeit von 1800 Sekunden.

Daraus ergibt sich folgende Konfigurationsdatei für unseren radvd:

 # vim /etc/radvd.conf
/etc/radvd.conf
# Configuration example for the router advertisement daemon radvd 
# for address assignment via SLAAC:
#  - M-flag: AdvManagedFlag = off (address configuration via SLAAC)
#  - O-flag: AdvOtherConfigFlag = on (obtaining a DNS server list 
#            and a domain name from a Stateless DHCPv6 server, but
#            not addressing information. 
#  - A-flag: AdvAutonomous = on (address configuration via SLAAC)
 
interface eth1
{
  # A  flag  indicating  whether or not the router sends periodic 
  # router advertisements and responds to router solicitations.
  # This option no longer has to be specified first, but it needs
  # to be on to enable advertisement on this interface.
  AdvSendAdvert on;
 
  # The  maximum  time  allowed between sending unsolicited multi-
  # cast router advertisements from the interface, in seconds.
  # Must be no less than 4 seconds and no greater than 1800 seconds.
  # Minimum when using Mobile IPv6 extensions: 0.07.
  # For values less than 0.2 seconds, 0.02 seconds is added to 
  # account for scheduling granularities as specified in RFC3775.
  MaxRtrAdvInterval 600;
 
  # The minimum time allowed between sending unsolicited multicast
  # router advertisements from the interface, in seconds.
  # Must be no less than 3 seconds and no greater than 
  # 0.75 * MaxRtrAdvInterval.
  # Minimum when using Mobile IPv6 extensions: 0.03.
  MinRtrAdvInterval 200;
 
  # The preference associated with the default router, as either 
  # "low", "medium", or "high".
  AdvDefaultPreference medium;
 
  # Mobile IPv6 support, when set, indicates that sending router is 
  # able to serve as Mobile IPv6 Home Agent.
  # When set, minimum limits specified by Mobile IPv6 are used for 
  # MinRtrAdvInterval and MaxRtrAdvInterval.
  AdvHomeAgentFlag off;
 
  # When set, hosts use the administered (stateful) protocol for 
  # address  autoconfiguration in  addition to any addresses 
  # autoconfigured using stateless address autoconfiguration.
  # The use of this flag is described in RFC 4862.
  # M-flag - if it is set to 1, this informs hosts that they can 
  # obtain a global address as well as DNS and a domain name from
  # a Stateful DHCPv6 server. Typically this means that auto-
  # addressing using SLAAC is not allowed on this segment and both
  # the A-flag and the O-flag are set to 0.
  AdvManagedFlag off;
 
  # When set, hosts use the administered (stateful) protocol for 
  # autoconfiguration of other (non-address) information.
  # The use of this flag is described in RFC 4862
  # O-flag - if it is set to on, this informs hosts that they can
  # obtain a DNS server list and a domain name from a Stateless 
  # DHCPv6 server, but not addressing information. Typically it 
  # works in conjunction with SLAAC for auto-addressing and both
  # the A-flag and the O-flag are set to on.
  #
  AdvOtherConfigFlag on;
 
  # The time, in milliseconds, that a node assumes a neighbor is 
  # reachable after having received a reachability confirmation.
  # Used by the Neighbor Unreachability Detection algorithm (see
  # Section 7.3 of RFC 4861).
  # A value of zero means unspecified (by this router).
  # Must be no greater than 3,600,000 milliseconds (1 hour).
  AdvReachableTime 0;
 
  # The time,in milliseconds, between retransmitted Neighbor Soli-
  # citation messages. Used by address resolution and the Neighbor
  # Unreachability Detection algorithm (see Sections 7.2 and 7.3 
  # of RFC 4861).  A value of zero means unspecified (by this router).
  AdvRetransTimer 0;
 
  # The default value that should be placed in the Hop Count field of
  # the IP header for outgoing (unicast) IP packets. The value should
  # be set to the current diameter of the Internet.
  # The value zero means unspecified (by this router).
  AdvCurHopLimit 64;
 
  # The lifetime associated with the default router in units of seconds.
  # The maximum value corresponds to 18.2 hours. A lifetime of 0 indi-
  # cates that the router is not a default router and should not appear
  # on the default router list. The router lifetime applies only to the
  # router's usefulness as a default router; it does not apply to in-
  # formation contained in other message fields or options. Options that
  # need time limits for their information include their own lifetime 
  # fields.
  # Must be either zero or between MaxRtrAdvInterval and 9000 seconds.
  # Default: 3 * MaxRtrAdvInterval (Minimum 1 second).
  AdvDefaultLifetime 1800;
 
  # When set, the link-layer address of the outgoing interface is 
  # included in the RA.
  AdvSourceLLAddress on;
 
  # global-scope address prefix
  prefix 2001:a:bcd:1234::/64
  {
    # When set, indicates that this prefix can be used for on-link 
    # determination. When not set the advertisement makes no statement
    # about on-link or off-link properties of the prefix. For instance,
    # the prefix might be used for address configuration with some of
    # the addresses belonging to the prefix being on-link and others 
    # being off-link.
    AdvOnLink on;
 
    # When set, indicates that this prefix can be used for autonomous 
    # address configuration as specified in RFC 4862.
    # A-flag - if it is set to on, this informs hosts that they can 
    # auto-generate GUA address using SLAAC. If it is set to off means
    # that auto-configuration is not allowed for this segment.
    AdvAutonomous on;
 
    # When set, indicates that the address of interface is sent instead
    # of network prefix, as is required by Mobile IPv6. When set, 
    # minimum limits specified by Mobile IPv6 are used for
    # MinRtrAdvInterval and MaxRtrAdvInterval.
    AdvRouterAddr off;
 
    # The length of time in seconds (relative to the time the packet is 
    # sent) that the prefix is valid for the purpose of on-link de-
    # termination. The symbolic value infinity represents infinity 
    # (i.e. a value of all one bits (0xffffffff)). The valid lifetime
    # is also used by RFC 4862.
    #
    # Note that clients will ignore AdvValidLifetime of an existing
    # prefix if the lifetime is below two hours, as required in RFC
    # 4862 Section 5.5.3 point e).
    # Note: RFC4861's suggested default value is significantly longer:
    # 30 days.
    AdvValidLifetime 5400;
 
    # The length of time in seconds (relative to the time the packet
    # is sent) that addresses generated from the prefix via stateless
    # address autoconfiguration remain preferred. The symbolic value
    # infinity represents infinity (i.e. a value of all one bits
    # (0xffffffff)).  See RFC 4862.
    #
    # Note: RFC4861's suggested default value is significantly longer:
    # 7 days.
    AdvPreferredLifetime 2700;
    };
 
  # route for global-scope address prefix
  route 2001:a:bcd:1234::/64
  {
    # The preference associated with the default router, as either 
    # "low", "medium", or "high".
    AdvRoutePreference medium;
 
    # The lifetime associated with the route in units of seconds. The
    # symbolic value infinity represents infinity (i.e. a value of
    # all one bits (0xffffffff)).
    #
    # Default: 3 * MaxRtrAdvInterval
    AdvRouteLifetime 1800;
  };
 
  # unique local prefix
  prefix fdb6:cb48:9d77:0::/64
  {
    # When set, indicates that this prefix can be used for on-link 
    # determination. When not set the advertisement makes no statement
    # about on-link or off-link properties of the prefix. For instance,
    # the prefix might be used for address configuration with some of
    # the addresses belonging to the prefix being on-link and others 
    # being off-link.
    AdvOnLink on;  
 
    # When set, indicates that this prefix can be used for autonomous 
    # address configuration as specified in RFC 4862.
    # A-flag - if it is set to on, this informs hosts that they can 
    # auto-generate GUA address using SLAAC. If it is set to off means
    # that auto-configuration is not allowed for this segment.
    AdvAutonomous on;
 
    # When set, indicates that the address of interface is sent instead
    # of network prefix, as is required by Mobile IPv6. When set, 
    # minimum limits specified by Mobile IPv6 are used for
    # MinRtrAdvInterval and MaxRtrAdvInterval.
    AdvRouterAddr off;
 
    # The length of time in seconds (relative to the time the packet is 
    # sent) that the prefix is valid for the purpose of on-link de-
    # termination. The symbolic value infinity represents infinity 
    # (i.e. a value of all one bits (0xffffffff)). The valid lifetime
    # is also used by RFC 4862.
    #
    # Note that clients will ignore AdvValidLifetime of an existing
    # prefix if the lifetime is below two hours, as required in RFC
    # 4862 Section 5.5.3 point e).
    # Note: RFC4861's suggested default value is significantly longer:
    # 30 days.
    AdvValidLifetime 5400;
 
    # The length of time in seconds (relative to the time the packet
    # is sent) that addresses generated from the prefix via stateless
    # address autoconfiguration remain preferred. The symbolic value
    # infinity represents infinity (i.e. a value of all one bits
    # (0xffffffff)).  See RFC 4862.
    #
    # Note: RFC4861's suggested default value is significantly longer:
    # 7 days.
    AdvPreferredLifetime 2700;
    };             
 
  # route for unique local prefix
  route fdb6:cb48:9d77:0::/64
  {
    # The preference associated with the default router, as either 
    # "low", "medium", or "high".
    AdvRoutePreference medium;
 
    # The lifetime associated with the route in units of seconds. The
    # symbolic value infinity represents infinity (i.e. a value of
    # all one bits (0xffffffff)).
    #                 
    # Default: 3 * MaxRtrAdvInterval
    AdvRouteLifetime 1800;
  };
 
};

Wollen wir die Kondfigurationsdate ohne die Kommentare sehen, grep'en wir einfach entspprechend danach.

 # grep -Ev '(^.*#|^$)' /etc/radvd.conf

Beispielkonfigurationsdatei ohne Kommentare

Bevor wir nun unseren radvd starten, führen wir noch einen Konfigurationstest durch. Hierbei hilft uns das radvd-Binary. Alle möglichen Optionen können wir uns hier mit der Option --help anzeigen lassen.

 # radvd --help
usage: radvd 
  -C, --config=PATH       Set the config file.  Default is /etc/radvd.d.
  -c, --configtest        Parse the config file and exit.
  -d, --debug=NUM         Set the debug level.  Values can be 1, 2, 3, 4 or 5.
  -f, --facility=NUM      Set the logging facility.
  -h, --help              Show this help screen.
  -l, --logfile=PATH      Set the log file.
  -m, --logmethod=X       Set method to: syslog, stderr, stderr_syslog, logfile,
                          stderr_clean, or none.
  -n, --nodaemon          Prevent the daemonizing.
  -p, --pidfile=PATH      Set the pid file.
  -t, --chrootdir=PATH    Chroot to the specified path.
  -u, --username=USER     Switch to the specified user.
  -v, --version           Print the version and quit.

Wir prüfen also nun die Konfigurationsdatei unseres radvd auf syntaktische Fehler.

 # radvd -cC /etc/radvd.conf
[Jun 28 17:38:26] radvd (1284): config file, /etc/radvd.conf, syntax ok

Nun starten wir unseren radvd Daemon.

 # systemctl start radvd.service

Im journald wir der Start entsprechend dokumentiert.

 # journalctl -fu radvd
Jun 28 17:42:47 vml000110 systemd[1]: Started IPv6 Router Advertisement Daemon.
Jun 28 17:42:47 vml000110 radvd[1317]: [Jun 28 17:42:47] radvd (1317): version 2.19 started

Bei Beadrf können wir natürlich auch den Status unseres Daemons jederzeit abfragen.

 # systemctl status radvd.service

 radvd.service - IPv6 Router Advertisement Daemon
     Loaded: loaded (/usr/lib/systemd/system/radvd.service; disabled; preset: disabled)
   Active:active (running) since Fri 2024-06-28 17:42:47 CEST; 11min ago
 Invocation: 3d6734874ec54a44b3e94fa6cbebee0a
   Main PID: 1317 (radvd)
      Tasks: 2 (limit: 9510)
     Memory: 380K (peak: 1.5M)
        CPU: 15ms
     CGroup: /system.slice/radvd.service
             ├─1317 /usr/bin/radvd --nodaemon
             └─1318 /usr/bin/radvd --nodaemon

Jun 28 17:42:47 vml000110 systemd[1]: Started IPv6 Router Advertisement Daemon.
Jun 28 17:42:47 vml000110 radvd[1317]: [Jun 28 17:42:47] radvd (1317): version 2.19 started

Nun prüfen wir, ob unser radvd auch die richtigen Router Advertisement ICMPv6 Nachrichten ins Netz schickt. Hier bieten sich zwei mögliche Varianten an:

  1. Mit dem Programm radvdump aus dem Paket radvd. Hierzu starten wir dias besagte Binary auf einem unserer Clients im lokalen Netzwerk-Segment dieses Binary.
     # radvdump
    #
    # radvd configuration generated by radvdump 2.18
    # based on Router Advertisement from fe80::10:ff:fe10:110
    # received by interface enp0s25
    #
    
    interface enp0s25
    {
    	AdvSendAdvert on;
    	# Note: {Min,Max}RtrAdvInterval cannot be obtained with radvdump
    	AdvManagedFlag off;
    	AdvOtherConfigFlag on;
    	AdvReachableTime 0;
    	AdvRetransTimer 0;
    	AdvCurHopLimit 64;
    	AdvDefaultLifetime 1800;
    	AdvHomeAgentFlag off;
    	AdvDefaultPreference medium;
    	AdvSourceLLAddress on;
    
    	prefix 2001:a:bcd:1234::/64
    	{
    		AdvValidLifetime 5400;
    		AdvPreferredLifetime 2700;
    		AdvOnLink on;
    		AdvAutonomous on;
    		AdvRouterAddr off;
    	}; # End of prefix definition
    
    
    	prefix fdb6:cb48:9d77::/64
    	{
    		AdvValidLifetime 5400;
    		AdvPreferredLifetime 2700;
    		AdvOnLink on;
    		AdvAutonomous on;
    		AdvRouterAddr off;
    	}; # End of prefix definition
    
    
    	route 2001:a:bcd:1234::/64
    	{
    		AdvRoutePreference medium;
    		AdvRouteLifetime 1800;
    	}; # End of route definition
    
    
    	route fdb6:cb48:9d77::/64
    	{
    		AdvRoutePreference medium;
    		AdvRouteLifetime 1800;
    	}; # End of route definition
    
    }; # End of interface definition

    In regelmäßigen Abständen tauchen also diese RA-Meldungen auf.

  2. Mit Hilfe von tcpdump können wir auch die RA-Meldungen mitschneiden und darstellen, in nachfolgenden Beispiel ist der Name des Netzwerkinterfaces enp0s15.
     # tcpdump -vi enp0s25 "icmp6[icmp6type] == icmp6-routeradvert"
    tcpdump: listening on enp0s25, link-type EN10MB (Ethernet), snapshot length 262144 bytes
    18:09:46.840357 IP6 (flowlabel 0xc155a, hlim 255, next-header ICMPv6 (58) payload length: 136) _gateway > nitrop
      hop limit 64, Flags [other stateful], pref medium, router lifetime 1800s, reachable time 0ms, retrans timer 0m
        prefix info option (3), length 32 (4): 2001:a:bcd:1234::/64, Flags [onlink, auto], valid time 5400s, pref. t
        prefix info option (3), length 32 (4): fdb6:cb48:9d77::/64, Flags [onlink, auto], valid time 5400s, pref. ti
        route info option (24), length 24 (3):  2001:a:bcd:1234::/64, pref=medium, lifetime=1800s                   
        route info option (24), length 24 (3):  fdb6:cb48:9d77::/64, pref=medium, lifetime=1800s
        source link-address option (1), length 8 (1): 52:54:00:41:11:02
    ^C
    1 packet captured
    1 packet received by filter
    0 packets dropped by kernel

Verbindet sich nun ein Client mit dem Netzwerk, handelt dieser eigenständig seine IPv6-Adressen, wie unter Was ist SLAAC und wie funktioniert es beschrieben, aus. Der radvd protokolliert dies aber nicht im journald, da diese von der Adressgenerierung und erfolgreichen DOD nicht weiß!

SLAAC und privacy extension - Konfiguration der (Arch Linux) Clients

Wie wir im Abschnitt Was ist SLAAC und wie funktioniert es gesehen haben wird mit unter die MAC-Adresse der Netzwerkschnittstelle bei der automatischen Generierung der IPv6-Adressen herangezogen. MAC-Adressen sind weltweit eindeutig d.h. die Ethernet-Schnittstelle des Client-Rechners hat eine MAC-Adresse, die es nirgendwo sonst auf der Welt gibt, ebenso das Interface für WLAN oder WWAN, je nachdem was im Rechner verbaut ist. Durch die Verwendung der MAC-Adresse einer Schnittstelle als Teil der IPv6-Adresse wird sicher gestellt, dass jedes Mal eine bzw. mehrere eindeutige IPv6-Adresse generiert werden.

Das Problem mit der Eindeutigkeit ist jedoch auch, dass sie auch als Kennung fungieren kann und man unter Umständen über diese Kennung dann weltweit trackbar ist, egal mit welchem IPv6-Netzwerk man sich verbunden hat!

Nutzt der Netzbetreiber bzw. der Betreiber eines IPv6-fähigen Netzwerkes SLAAC, ist man anhand der letzten 48 Bits der IPv6-Adresse trackbar, da diese eindeutig ja eineindeutig ist. Betreiber von Websites, die man nun besucht, können sehen, dass man zwar eine neue IP-Adresse haben, weil man zu einem anderen Betreiber wechselte. Die Webseitenanbieter können nun aber auch sehen, dass die letzten 48 Bits der Adresse jedes Mal gleich bleiben. Daher kennt jede Website, die man besucht, das Gerät, unabhängig davon, in welchem Netz man sich befindet! So kann man sehr leicht anbieterübergreifend nachverfolgt werden!

Dieses Problematik hat man erkannt und das SLAAC-Protokoll im RFC 4941 - Privacy Extensions for Stateless Address Autoconfiguration in IPv6 „erweitert“ bzw. die Lösung beschrieben. Vereinfacht dargestellt, verwendet der Host nicht mehr die MAC-Adresse der Netzwerkschnittstelle, um die letzten 48 Stellen seiner IPv6-Adresse auszufüllen. Stattdessen eine Reihe von Bits nach dem Zufallsprinzip ausgewählt und statt der MAC-Adresse der Schnittstelle verwendet um die letzten 48 Bits der IPv6-Adresse zu generieren.

Ein weiterer grosser Vorteil der Privacy Extensions bei SLAAC ist, dass Adressen eine Zeitüberschreitung erfahren. Nach einer konfigurierbaren Zeitspanne werden die Schnittstellenadressen veraltet und können nicht mehr von der Netzwerkschnittstelle verwendet werden. In der Regel beträgt dieser Zeitraum 24 Stunden, also einen Tag - das bedeutet, dass die Schnittstelle jeden Tag eine neue IP-Adresse erhält. Dies macht es nun schwieriger, einen einzelnen Benutzer einer bestimmten MAC- oder sogar IP-Adresse zuzuordnen.

Sehen wir uns also an, wie ein Client seine IPv6-Adressen generiert. Unser Laptop hat noch keine Verbindung zum Netzwerk, da das Ethernet-Kabel nicht angesteckt ist. Wir sehen das unter anderem an der IP-Adress-Einstellungen:

 # p addr show enp0s25
2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000      
    link/ether 50:7b:9d:91:52:54 brd ff:ff:ff:ff:ff:ff

Unser Laptop hat also noch keine LLA generiert. Wie wir wissen passiert das am Anfang beim 1. Schritt - Der Host generiert sich selbst eine LLA (Link Local Address).

Stecken wir nun das Netzwerkkabel an unseren Laptop und beobachten journald.

 # journalctl -fu NetworkManager
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2177] device (enp0s25): carrier: link connected
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2185] device (enp0s25): state change: unavailable -> disconnected (reason 'carrier-changed', sys-iface-state: 'managed')
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2213] policy: auto-activating connection 'enp0s25' (8b61d72d-e99c-3480-b588-4dac6f16086e)
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2230] device (enp0s25): Activation: starting connection 'enp0s25' (8b61d72d-e99c-3480-b588-4dac6f16086e)
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2234] device (enp0s25): state change: disconnected -> prepare (reason 'none', sys-iface-state: 'managed')
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2243] manager: NetworkManager state is now CONNECTING
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2249] device (enp0s25): state change: prepare -> config (reason 'none', sys-iface-state: 'managed')
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2263] device (enp0s25): state change: config -> ip-config (reason 'none', sys-iface-state: 'managed')
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2288] dhcp4 (enp0s25): activation: beginning transaction (timeout in 45 seconds)
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.2331] dhcp4 (enp0s25): state changed new lease, address=10.0.10.74, acd pending
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.3881] dhcp4 (enp0s25): state changed new lease, address=10.0.10.74
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.3885] policy: set 'enp0s25' (enp0s25) as default for IPv4 routing and DNS
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.3962] device (enp0s25): state change: ip-config -> ip-check (reason 'none', sys-iface-state: 'managed')
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.4330] device (enp0s25): state change: ip-check -> secondaries (reason 'none', sys-iface-state: 'managed')
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.4332] device (enp0s25): state change: secondaries -> activated (reason 'none', sys-iface-state: 'managed')
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.4337] manager: NetworkManager state is now CONNECTED_SITE
Jun 28 21:21:39 pml010074 NetworkManager[1149]: <info>  [1719602499.4340] device (enp0s25): Activation: successful, device activated.
Jun 28 21:21:40 pml010074 NetworkManager[1149]: <info>  [1719602500.5188] dhcp6 (enp0s25): activation: beginning transaction (timeout in 45 seconds)
Jun 28 21:21:40 pml010074 NetworkManager[1149]: <info>  [1719602500.5201] policy: set 'enp0s25' (enp0s25) as default for IPv6 routing and DNS
Jun 28 21:21:40 pml010074 NetworkManager[1149]: <info>  [1719602500.5221] dhcp6 (enp0s25): state changed new lease

Fragen wir die IP-Adresse des Netzwerkinterfaces ab sehen wir:

 # ip addr show enp0s25 
2: enp0s25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 50:7b:9d:91:52:54 brd ff:ff:ff:ff:ff:ff
    inet 10.0.10.74/24 brd 10.0.10.255 scope global dynamic noprefixroute enp0s25
       valid_lft 3558sec preferred_lft 3558sec
    inet6 2001:a:bcd:1234:32f4:2aac:f2e1:5f73/64 scope global dynamic noprefixroute 
       valid_lft 5358sec preferred_lft 2658sec
    inet6 fdb6:cb48:9d77:0:e596:e316:4695:85b6/64 scope global dynamic noprefixroute 
       valid_lft 5358sec preferred_lft 2658sec
    inet6 fe80::fa4e:fbee:c806:f070/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

Moment mal, das sieht doch eigentlich wie gewohnt aus, nichts besonderes, nichts von einer scope global dynamic mngtmpaddr (stabile dynamische IPv6 Adresse) für eingehende Verbindungen oder scope global temporary dynamic (temporäre „privacy“ IPv6 Adresse) für ausgehende Verbindungen zu sehen!

Warum ist das nun so? Ganz einfach, weil am Client-Renchner noch keine Privacy Extension ausgewählt wurde. Werfen wir einen Blick in die betreffende Konfigurationsdatei /etc/sysctl.d/10-ipv6-privacy.conf.

 # vim /etc/sysctl.d/10-ipv6-privacy.conf
/etc/sysctl.d/10-ipv6-privacy.conf
# Django : manual on 2024-06-27
# IPv6 Privacy Extensions (RFC 4941)
# ---
# IPv6 typically uses a device's MAC address when choosing an IPv6 address
# to use in autoconfiguration. Privacy extensions allow using a randomly
# generated IPv6 address, which increases privacy.
#
# Acceptable values:
#    0 - don’t use privacy extensions.
#    1 - generate privacy addresses
#    2 - prefer privacy addresses and use them over the normal addresses.
net.ipv6.conf.all.use_tempaddr = 0
net.ipv6.conf.default.use_tempaddr = 0

O.K. dann stellen wir das doch gleich mal um auf 2 = prefer privacy addresses and use them over the normal addresses. Zuvor trennen wir aber noch die Netzwerkverbindung in dem wir das Netzwerkkabel ziehen.

 # vim /etc/sysctl.d/10-ipv6-privacy.conf
/etc/sysctl.d/10-ipv6-privacy.conf
# Django : manual on 2024-06-28
# IPv6 Privacy Extensions (RFC 4941)
# ---
# IPv6 typically uses a device's MAC address when choosing an IPv6 address
# to use in autoconfiguration. Privacy extensions allow using a randomly
# generated IPv6 address, which increases privacy.
#
# Acceptable values:
#    0 - don’t use privacy extensions.
#    1 - generate privacy addresses
#    2 - prefer privacy addresses and use them over the normal addresses.
net.ipv6.conf.all.use_tempaddr = 2
net.ipv6.conf.default.use_tempaddr = 2

Nach Änderung der Konfigurationsdatei müssen wir zum Aktivieren der geänderten Optionen in der sysctl-Datei ohne Neustart des Rechners folgenden Befehl ausführen:

 # sysctl --system

Stecken wir nun das Netzwerkkabel wie ein und fragen erneut die IP-Adressen der Netzwerkschnittstelle ab.

 # ip addr show enp0s25 
2: enp0s25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 50:7b:9d:91:52:54 brd ff:ff:ff:ff:ff:ff
    inet 10.0.10.74/24 brd 10.0.10.255 scope global dynamic noprefixroute enp0s25
       valid_lft 3597sec preferred_lft 3597sec
    inet6 2001:a:bcd:1234:d4d0:5fec:f740:3561/64 scope global temporary dynamic 
       valid_lft 5398sec preferred_lft 2698sec
    inet6 2001:a:bcd:1234:32f4:2aac:f2e1:5f73/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 5398sec preferred_lft 2698sec
    inet6 fdb6:cb48:9d77:0:4ec1:8ad3:1549:fc33/64 scope global temporary dynamic 
       valid_lft 5398sec preferred_lft 2698sec
    inet6 fdb6:cb48:9d77:0:e596:e316:4694:85b7/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 5398sec preferred_lft 2698sec
    inet6 fe80::fa4e:fbee:c806:f070/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

Wie sehen also nun, dass jeweils bei der GUA und bei der ULA jeweils zwei Adressen auftauchen, jeweils mit einer Gültigkeit von noch 2698 Sekunden, also kanpp eine 3/4 Stunde, dann werden diese neu ausgehandelt!

Wir haben zwei Adressen via SLACC bekommen, eine stabile dynamische IPv6 Adresse scope global dynamic mngtmpaddr und temporäre „privacy“ IPv6 Adresse scope global temporary dynamic. Erstere ist für eingehende Verbindungen und letztere ist für ausgehende Verbindungen und wird alle gemäß der RA-Option AdvPreferredLifetime 2700 alle 45 Minuten neu ausgewürfelt.

WICHTIG:

Bei der zuvor angestellten Frage Was ist SLAAC und wie funktioniert es? haben wir bereits erkannt, dass in seiner aktuellen Implementierung, wie sie in RFC 4862 - IPv6 Stateless Address Autoconfiguration definiert ist, SLAAC den Hosts keine DNS-Serveradressen zur Verfügung stellt! Diese Informationen müssen wir noch gesondert den Clients mitgeben, sprich wir werden mit Hilfe eines Stateless DHCPv6-Servers realisieren. Bei der Konfiguration der Router Advertisement Nachrichten bei unserem radvd haben wir bereits mit der Definition des sog. O-Flags AdvOtherConfigFlag = on schon vorgenommen, dass das Abrufen einer DNS-Serverliste und einen Domain-Namen von einem Stateless DHCPv6-Server, aber keine keine Adressierungsinformationen zu erfolgen hat! Solch ein zustandsloser DHCPv6-Server stellt überhaupt keine IPv6-Adressen bereit, sondern liefert nur „andere Informationen“ wie eine DNS-Serverliste und einen Domänennamen, mehr nicht. Wir werden im Kapitel DHCPv4|v6-Server mit DHCP ISC Kea unter Arch Linux einrichten und nutzen noch detailliert eingehen!

Ein Stateful DHCPv6-Server liefert neben IPv6-Adressen auch weitere Informationen, wie z.B. wie eine DNS-Serverliste und einen Domänennamen, an einen Host aus. Hosts. Dieser Stateful DHCPv6-Server behält auch den Status jeder Zuweisung im Auge, sprich er verfolgt die Verfügbarkeit des Adresspools und löst doppelte Adresskonflikte auf. Darüber hinaus protokolliert er jede Zuweisung und behält die Ablaufzeiten im Auge. Im Gegensatz zu IPv4 stellt ein Stateful DHCPv6-Server den Hosts keine Standard-Gateway-Adressen zur Verfügung, das kann bei IPv6 nur Router, die Router Advertisement-Nachrichten sendet wie z.B. unser radvd!

Stateful DHCPv6 Konfiguration beim radvd

Im Abschnitt Grundlagen haben wir u.a. im Kapitel RA — Router Advertisement (ICMPv6 Type 134) gelernt, dass mit Hilfe von diversen Flags definiert werden kann, wie den Clients mitgeteilt werden kann, welche Art und Weise bei der IPv6-Zuweisung beschritten werden soll.

Bei unserem Konfigurationsbeispiel hier gehen wir für den Router Advertisement Daemon radvd für die Adressvergabe durch einen Stateful DHCPv6-Server von folgenden Eckwerten aus:

  • Netzwerkinterface :
    Der radvd soll nur auf dem Netzwerkinterface eth1 operieren, also dort lauscht er auf Router Solicitation ICMPv6-Nachrichten neuer Clients und beantwortet selbige mit Router Advertisements ICMPv6-Nachrichten bzw. sendet auf dieser Netzwerkschnittstelle regelmäßig seine Router Advertisements ICMPv6-Nachrichten an alle Clients im lokalen betreffenden Netz.
  • M-Flag:
    AdvManagedFlag = on (Adresskonfiguration via Stateful DHCPv6)
  • O-Flag:
    AdvOtherConfigFlag = on (Abrufen einer DNS-Serverliste und einen Domain-Namen von einem Stateless DHCPv6-Server, aber keine keine Adressierungsinformationen.
  • A-Flag:
    AdvAutonomous = off (Adresskonfiguration via Statful DHCPv6)
  • Route für den Global-Scope Address Prefix 2001:a:bcd:1234:
    2001:a:bcd:1234::/64 und eine Gültigkeit von einer 1/2 Stunde, also 1800 Sekunden.
  • Route für den Unique Local IPv6 prefix : fdb6:cb48:9d77:0::/64
    fdb6:cb48:9d77:0::/64 ebenfalls eine Gültigkeit von 1800 Sekunden.

Daraus ergibt sich folgende Konfigurationsdatei für unseren radvd:

 # vim /etc/radvd.conf
/etc/radvd.conf
# Configuration example for the router advertisement daemon radvd 
# for address assignment via DHCPv6:
#  - M-flag: AdvManagedFlag = on (address configuration via DHCPv6)
#  - O-flag: AdvOtherConfigFlag = on (obtaining a DNS server list 
#            and a domain name from a Stateless DHCPv6 server, but
#            not addressing information. 
#  - A-flag: AdvAutonomous = off (address configuration via DHCPv6)
 
interface eth1
{
  # A  flag  indicating  whether or not the router sends periodic 
  # router advertisements and responds to router solicitations.
  # This option no longer has to be specified first, but it needs
  # to be on to enable advertisement on this interface.
  AdvSendAdvert on;
 
  # The  maximum  time  allowed between sending unsolicited multi-
  # cast router advertisements from the interface, in seconds.
  # Must be no less than 4 seconds and no greater than 1800 seconds.
  # Minimum when using Mobile IPv6 extensions: 0.07.
  # For values less than 0.2 seconds, 0.02 seconds is added to 
  # account for scheduling granularities as specified in RFC3775.
  MaxRtrAdvInterval 600;
 
  # The minimum time allowed between sending unsolicited multicast
  # router advertisements from the interface, in seconds.
  # Must be no less than 3 seconds and no greater than 
  # 0.75 * MaxRtrAdvInterval.
  # Minimum when using Mobile IPv6 extensions: 0.03.
  MinRtrAdvInterval 200;
 
  # The preference associated with the default router, as either 
  # "low", "medium", or "high".
  AdvDefaultPreference medium;
 
  # Mobile IPv6 support, when set, indicates that sending router is 
  # able to serve as Mobile IPv6 Home Agent.
  # When set, minimum limits specified by Mobile IPv6 are used for 
  # MinRtrAdvInterval and MaxRtrAdvInterval.
  AdvHomeAgentFlag off;
 
  # When set, hosts use the administered (stateful) protocol for 
  # address  autoconfiguration in  addition to any addresses 
  # autoconfigured using stateless address autoconfiguration.
  # The use of this flag is described in RFC 4862.
  # M-flag - if it is set to 1, this informs hosts that they can 
  # obtain a global address as well as DNS and a domain name from
  # a Stateful DHCPv6 server. Typically this means that auto-
  # addressing using SLAAC is not allowed on this segment and both
  # the A-flag and the O-flag are set to 0.
  AdvManagedFlag on;
 
  # When set, hosts use the administered (stateful) protocol for 
  # autoconfiguration of other (non-address) information.
  # The use of this flag is described in RFC 4862
  # O-flag - if it is set to on, this informs hosts that they can
  # obtain a DNS server list and a domain name from a Stateless 
  # DHCPv6 server, but not addressing information. Typically it 
  # works in conjunction with SLAAC for auto-addressing and both
  # the A-flag and the O-flag are set to on.
  #
  AdvOtherConfigFlag on;
 
  # The time, in milliseconds, that a node assumes a neighbor is 
  # reachable after having received a reachability confirmation.
  # Used by the Neighbor Unreachability Detection algorithm (see
  # Section 7.3 of RFC 4861).
  # A value of zero means unspecified (by this router).
  # Must be no greater than 3,600,000 milliseconds (1 hour).
  AdvReachableTime 0;
 
  # The time,in milliseconds, between retransmitted Neighbor Soli-
  # citation messages. Used by address resolution and the Neighbor
  # Unreachability Detection algorithm (see Sections 7.2 and 7.3 
  # of RFC 4861).  A value of zero means unspecified (by this router).
  AdvRetransTimer 0;
 
  # The default value that should be placed in the Hop Count field of
  # the IP header for outgoing (unicast) IP packets. The value should
  # be set to the current diameter of the Internet.
  # The value zero means unspecified (by this router).
  AdvCurHopLimit 64;
 
  # The lifetime associated with the default router in units of seconds.
  # The maximum value corresponds to 18.2 hours. A lifetime of 0 indi-
  # cates that the router is not a default router and should not appear
  # on the default router list. The router lifetime applies only to the
  # router's usefulness as a default router; it does not apply to in-
  # formation contained in other message fields or options. Options that
  # need time limits for their information include their own lifetime 
  # fields.
  # Must be either zero or between MaxRtrAdvInterval and 9000 seconds.
  # Default: 3 * MaxRtrAdvInterval (Minimum 1 second).
  AdvDefaultLifetime 1800;
 
  # When set, the link-layer address of the outgoing interface is 
  # included in the RA.
  AdvSourceLLAddress on;
 
  # global-scope adress prefix
  prefix 2001:a:bcd:1234::/64
  {
    # When set, indicates that this prefix can be used for on-link 
    # determination. When not set the advertisement makes no statement
    # about on-link or off-link properties of the prefix. For instance,
    # the prefix might be used for address configuration with some of
    # the addresses belonging to the prefix being on-link and others 
    # being off-link.
    AdvOnLink on;
 
    # When set, indicates that this prefix can be used for autonomous 
    # address configuration as specified in RFC 4862.
    # A-flag - if it is set to on, this informs hosts that they can 
    # auto-generate GUA address using SLAAC. If it is set to off means
    # that auto-configuration is not allowed for this segment.
    AdvAutonomous off;
 
    # When set, indicates that the address of interface is sent instead
    # of network prefix, as is required by Mobile IPv6. When set, 
    # minimum limits specified by Mobile IPv6 are used for
    # MinRtrAdvInterval and MaxRtrAdvInterval.
    AdvRouterAddr off;
 
    # The length of time in seconds (relative to the time the packet is 
    # sent) that the prefix is valid for the purpose of on-link de-
    # termination. The symbolic value infinity represents infinity 
    # (i.e. a value of all one bits (0xffffffff)). The valid lifetime
    # is also used by RFC 4862.
    #
    # Note that clients will ignore AdvValidLifetime of an existing
    # prefix if the lifetime is below two hours, as required in RFC
    # 4862 Section 5.5.3 point e).
    # Note: RFC4861's suggested default value is significantly longer:
    # 30 days.
    AdvValidLifetime 5400;
 
    # The length of time in seconds (relative to the time the packet
    # is sent) that addresses generated from the prefix via stateless
    # address autoconfiguration remain preferred. The symbolic value
    # infinity represents infinity (i.e. a value of all one bits
    # (0xffffffff)).  See RFC 4862.
    #
    # Note: RFC4861's suggested default value is significantly longer:
    # 7 days.
    AdvPreferredLifetime 2700;
    };
 
  # route for global-scope address prefix
  route 2001:a:bcd:1234::/64
  {
    # The preference associated with the default router, as either 
    # "low", "medium", or "high".
    AdvRoutePreference medium;
 
    # The lifetime associated with the route in units of seconds. The
    # symbolic value infinity represents infinity (i.e. a value of
    # all one bits (0xffffffff)).
    #
    # Default: 3 * MaxRtrAdvInterval
    AdvRouteLifetime 1800;
  };
 
  # unique local prefix
  prefix fdb6:cb48:9d77:0::/64
  {
    # When set, indicates that this prefix can be used for on-link 
    # determination. When not set the advertisement makes no statement
    # about on-link or off-link properties of the prefix. For instance,
    # the prefix might be used for address configuration with some of
    # the addresses belonging to the prefix being on-link and others 
    # being off-link.
    AdvOnLink on;  
 
    # When set, indicates that this prefix can be used for autonomous 
    # address configuration as specified in RFC 4862.
    # A-flag - if it is set to on, this informs hosts that they can 
    # auto-generate GUA address using SLAAC. If it is set to off means
    # that auto-configuration is not allowed for this segment.
    AdvAutonomous off;
 
    # When set, indicates that the address of interface is sent instead
    # of network prefix, as is required by Mobile IPv6. When set, 
    # minimum limits specified by Mobile IPv6 are used for
    # MinRtrAdvInterval and MaxRtrAdvInterval.
    AdvRouterAddr off;
 
    # The length of time in seconds (relative to the time the packet is 
    # sent) that the prefix is valid for the purpose of on-link de-
    # termination. The symbolic value infinity represents infinity 
    # (i.e. a value of all one bits (0xffffffff)). The valid lifetime
    # is also used by RFC 4862.
    #
    # Note that clients will ignore AdvValidLifetime of an existing
    # prefix if the lifetime is below two hours, as required in RFC
    # 4862 Section 5.5.3 point e).
    # Note: RFC4861's suggested default value is significantly longer:
    # 30 days.
    AdvValidLifetime 5400;
 
    # The length of time in seconds (relative to the time the packet
    # is sent) that addresses generated from the prefix via stateless
    # address autoconfiguration remain preferred. The symbolic value
    # infinity represents infinity (i.e. a value of all one bits
    # (0xffffffff)).  See RFC 4862.
    #
    # Note: RFC4861's suggested default value is significantly longer:
    # 7 days.
    AdvPreferredLifetime 2700;
    };             
 
  # 
  route fdb6:cb48:9d77:0::/64
  {
    # The preference associated with the default router, as either 
    # "low", "medium", or "high".
    AdvRoutePreference medium;
 
    # The lifetime associated with the route in units of seconds. The
    # symbolic value infinity represents infinity (i.e. a value of
    # all one bits (0xffffffff)).
    #                 
    # Default: 3 * MaxRtrAdvInterval
    AdvRouteLifetime 1800;
  };
 
};

Wollen wir die Kondfigurationsdate ohne die Kommentare sehen, grep'en wir einfach entsprechend danach.

 # grep -Ev '(^.*#|^$)' /etc/radvd.conf

Beispielkonfigurationsdatei ohne Kommentare

Bevor wir nun unseren radvd starten, führen wir noch einen Konfigurationstest durch. Wir prüfen also nun die Konfigurationsdatei unseres radvd auf syntaktische Fehler.

 # radvd -cC /etc/radvd.conf
[Jun 28 22:39:23] radvd (1835): config file, /etc/radvd.conf, syntax ok

Nun starten wir unseren radvd Daemon.

 # systemctl start radvd.service

Im journald wir der Start entsprechend dokumentiert.

 # journalctl -fu radvd
Jun 28 22:49:30 vml000110 systemd[1]: Started IPv6 Router Advertisement Daemon.
Jun 28 22:49:30 vml000110 radvd[1876]: [Jun 28 22:49:30] radvd (1876): version 2.19 started

Bei Bedarf können wir natürlich auch den Status unseres Daemons jederzeit abfragen.

 # systemctl status radvd.service

 radvd.service - IPv6 Router Advertisement Daemon
     Loaded: loaded (/usr/lib/systemd/system/radvd.service; disabled; preset: disabled)
   Active:active (running) since Fri 2024-06-28 22:49:30 CEST; 53s ago
 Invocation: 52f7f18768e246f2b63a5bad4717658b
   Main PID: 1876 (radvd)
      Tasks: 2 (limit: 9510)
     Memory: 368K (peak: 1.5M)
        CPU: 13ms
     CGroup: /system.slice/radvd.service
             ├─1876 /usr/bin/radvd --nodaemon
             └─1877 /usr/bin/radvd --nodaemon

Jun 28 22:49:30 vml000110 systemd[1]: Started IPv6 Router Advertisement Daemon.
Jun 28 22:49:30 vml000110 radvd[1876]: [Jun 28 22:49:30] radvd (1876): version 2.19 started

Nun prüfen wir, ob unser radvd auch die richtigen Router Advertisement ICMPv6 Nachrichten ins Netz schickt. Hier bieten sich zwei mögliche Varianten an:

  1. Mit dem Programm radvdump aus dem Paket radvd. Hierzu starten wir dias besagte Binary auf einem unserer Clients im lokalen Netzwerk-Segment dieses Binary.
     # radvdump
    #
    # radvd configuration generated by radvdump 2.18
    # based on Router Advertisement from fe80::10:ff:fe10:110
    # received by interface enp0s25
    #
    
    interface enp0s25
    {
    	AdvSendAdvert on;
    	# Note: {Min,Max}RtrAdvInterval cannot be obtained with radvdump
    	AdvManagedFlag on;
    	AdvOtherConfigFlag on;
    	AdvReachableTime 0;
    	AdvRetransTimer 0;
    	AdvCurHopLimit 64;
    	AdvDefaultLifetime 1800;
    	AdvHomeAgentFlag off;
    	AdvDefaultPreference medium;
    	AdvSourceLLAddress on;
    
    	prefix 2001:a:bcd:1234::/64
    	{
    		AdvValidLifetime 5400;
    		AdvPreferredLifetime 2700;
    		AdvOnLink on;
    		AdvAutonomous off;
    		AdvRouterAddr off;
    	}; # End of prefix definition
    
    
    	prefix fdb6:cb48:9d77::/64
    	{
    		AdvValidLifetime 5400;
    		AdvPreferredLifetime 2700;
    		AdvOnLink on;
    		AdvAutonomous off;
    		AdvRouterAddr off;
    	}; # End of prefix definition
    
    
    	route 2001:a:bcd:1234::/64
    	{
    		AdvRoutePreference medium;
    		AdvRouteLifetime 1800;
    	}; # End of route definition
    
    
    	route fdb6:cb48:9d77::/64
    	{
    		AdvRoutePreference medium;
    		AdvRouteLifetime 1800;
    	}; # End of route definition
    
    }; # End of interface definition

    In regelmäßigen Abständen tauchen also diese RA-Meldungen auf.

  2. Mit Hilfe von tcpdump können wir auch die RA-Meldungen mitschneiden und darstellen, in nachfolgenden Beispiel ist der Name des Netzwerkinterfaces enp0s25.
     # tcpdump -vi enp0s25 "icmp6[icmp6type] == icmp6-routeradvert"
    cpdump: listening on enp0s25, link-type EN10MB (Ethernet), snapshot length 262144 bytes
    22:58:47.643378 IP6 (flowlabel 0xc155a, hlim 255, next-header ICMPv6 (58) payload length: 136) _gateway > nitropad: [icmp6 sum ok] ICMP6, router advertisement, length 136
    	hop limit 64, Flags [managed, other stateful], pref medium, router lifetime 1800s, reachable time 0ms, retrans timer 0ms
    	  prefix info option (3), length 32 (4): 2001:a:bcd:1234::/64, Flags [onlink], valid time 5400s, pref. time 2700s
    	  prefix info option (3), length 32 (4): fdb6:cb48:9d77::/64, Flags [onlink], valid time 5400s, pref. time 2700s
    	  route info option (24), length 24 (3):  2001:a:bcd:1234::/64, pref=medium, lifetime=1800s
    	  route info option (24), length 24 (3):  fdb6:cb48:9d77::/64, pref=medium, lifetime=1800s
    	  source link-address option (1), length 8 (1): 52:54:00:41:11:02
    
    ^C
    1 packet captured
    1 packet received by filter
    0 packets dropped by kernel

Verbindet sich nun ein Client mit dem Netzwerk, handelt dieser nicht eigenständig seine IPv6-Adressen aus, sondern richtet eine entsprechende Anfrage an den DHCPv6-Server!

Natürlich wird man im Jahr 2024 nicht mehr ernsthaft, manuell Server aufsetzen und betreiben wollen. Vielmehr wird man auf ein Orchestrierungswerkzeug wie z.B. Ansible zurückgreifen. Setzen wir einen neue virtuellen Server unter Arch Linux neu auf, oder wollen wir bei einem bestehenden Host die Konfiguration aktualisieren, verwenden wir wie zuvor schon angeschnitten Ansible als Orchestrierungswerkzeug. So ist sichergestellt dass zum einen all unsere Hosts entsprechend gleich aufgebaut, konfiguriert und betrieben werden.

Wir werden uns nun nachfolgend die Server-Installation und -konfiguration genauer betrachten.

Der ungeduldigen Leser kann auch direkt zur Tat schreiten und das manuelle Anlegen der Inventory-Hülle, des Playbooks und der zugehörigen Rolle überspringen und diese Aufgaben mit folgendem Befehl sozusagen auf einem Rutsch erledigen:

 $ mkdir -p ~/devel/ansible ; wget https://gitlab.nausch.org/django/example_radvd/-/archive/main/example_radvd-main.tar.gz -O - | tar -xz --strip-components=1 -C ~/devel/ansible

Nach Anpassung der Daten im Inventory kann man anschliessend direkt zur Ausführung schreiten.

Vorbereitung - (Server-)Daten im Inventory

Bei unserem Konfigurationsbeispiel hier gehen wir von folgenden Host-Parametern aus:

  • zone: intra
  • hostname: vml010110

Die Konfigurationsdatei unseres inventory in unsere, Ansible-Verzeichnis beinhaltet demnach unter anderem:

 $ vim inventories/production/hosts

inventories/production/hosts

Bei den Host-Variablen definieren wir über die Variable radvd_ipv6_mode, wie in unserer Umgebung die IPv6-Adressen letztlich generiert bzw. verteilt werden sollen. Wollen wir SLAAC - IPv6 Stateless Address Auto-Configuration in unserem Netzwerk-(segment) nutzen, so setzen die die Variable radvd_ipv6_mode: „slaac“. Wollen wir hingegen IPv6 Stateful DHCPv6 nutzen, so setzen wir die Variable radvd_ipv6_mode: „dhcp6“.

Bei der Definition unseres KVM-Hosts hatten wir unter anderem definiert:

  • guest_nic_2 : "eth1"
  • guest_ip6_net_2 : "2003:a:bcd:1234::"
  • guest_mask6_2 : "/64"
  • guest_ip6_ls_fx_2 : "fdb6:cb48:9d77:0::"
  • guest_zone_2 : "intra"

inventories/production/host_vars/vml010110/kvm_vhost

Die für den radvd relevanten Konfigurationsparameter legen wir in der Inventrory-Datei inventories/production/host_vars/vml010110/radvd ab.

 $ vim inventories/production/host_vars/vml010110/radvd 

inventories/production/host_vars/vml010110/radvd

Playbook

Unser Playbook zum Installieren und Konfigurieren unseres Router Advertisement Daemon radvd, ist unscheinbar und unspektakulär.

 $ vim playbooks/arch_radvd.yml
playbooks/arch_radvd.yml
---
 
# Ansible Playbook zum Konfigurieren des Router Advertisement Daemon unter Arch-Linux.
# Aufruf via $ ansible-playbook playbooks/arch_radvd.yml :
#  $ ansible-playbook playbooks/arch_radvd.yml
# für einen Host aus der Hostgruppe DMZ.

- name: "Playbook-Name: arch_chrony_server.yml" # Name des Playbooks
  hosts: vml010110                              # Hostname/-gruppe für die das Playbook gelten soll

  roles:
    - role: radvd                               # radvd installieren und konfigurieren
      tags: radvd                               # Tag-Kennzeichnung der definierten Rolle
...

Rolle

Für die Konfiguration unseres radvd verwenden wir eine eigene Rolle radvd, die wir bei unserem zuvor angelegten Playbooks später einfach mit aufrufen werden. hierzu kopieren wir uns zunächst die Mustervorlage common.

 $ cp -avr roles/common/ roles/radvd
'roles/common/' -> 'roles/radvd'
'roles/common/defaults' -> 'roles/radvd/defaults'
'roles/common/defaults/.gitkeep' -> 'roles/radvd/defaults/.gitkeep'
'roles/common/files' -> 'roles/radvd/files'
'roles/common/files/.gitkeep' -> 'roles/radvd/files/.gitkeep'
'roles/common/handlers' -> 'roles/radvd/handlers'
'roles/common/handlers/.gitkeep' -> 'roles/radvd/handlers/.gitkeep'
'roles/common/library' -> 'roles/radvd/library'
'roles/common/library/.gitkeep' -> 'roles/radvd/library/.gitkeep'
'roles/common/lookup_plugins' -> 'roles/radvd/lookup_plugins'
'roles/common/lookup_plugins/.gitkeep' -> 'roles/radvd/lookup_plugins/.gitkeep'
'roles/common/meta' -> 'roles/radvd/meta'
'roles/common/meta/.gitkeep' -> 'roles/radvd/meta/.gitkeep'
'roles/common/module_utils' -> 'roles/radvd/module_utils'
'roles/common/module_utils/.gitkeep' -> 'roles/radvd/module_utils/.gitkeep'
'roles/common/tasks' -> 'roles/radvd/tasks'
'roles/common/tasks/main.yml' -> 'roles/radvd/tasks/main.yml'
'roles/common/templates' -> 'roles/radvd/templates'
'roles/common/templates/.gitkeep' -> 'roles/radvd/templates/.gitkeep'
'roles/common/vars' -> 'roles/radvd/vars'
'roles/common/vars/.gitkeep' -> 'roles/radvd/vars/.gitkeep'

Bei Bedarf können wir uns die Struktur die somit angelegt wurde mit nachfolgendem Befehl anzeigen lassen.

 $ tree roles/radvd/

Ausgabe von tree roles/radvd/

Wie wir sehen ist die Rolle durchaus überschaubar, im Task main.yaml verweisen wir lediglich auf die beiden eigentlichen Tasks install.yml und firewalld.yml

 $ vim roles/radvd/tasks/main.yml
roles/radvd/tasks/main.yml
---

- name: "Prüfen ob die Variablen für GUA und ULA valide Werte haben."
  ansible.builtin.include_tasks:
    file: variablencheck.yml
    apply:
      tags: variablencheck

- name: "Installation und Konfiguration des Router Advertisement Daemon radvd."
  ansible.builtin.include_tasks:
    file: install.yml
    apply:
      tags: install

- name: "Konfiguration des firewalld für den Router Advertisement Daemon radvd."
  ansible.builtin.include_tasks:
    file: firewalld.yml
    apply:
      tags: firewalld
 
...

Die eigentliche Installation und Konfiguration erfolgt dann im Task install.yml.

 $ vim roles/radvd/tasks/install.yml
roles/radvd/tasks/install.yml
---

- name: "Installation des Router Advertisement Daemon radvd."
  community.general.pacman:
    name: radvd
    state: present

- name: "Checken ob es bereits eine Backupdatei der radvd.conf gibt."
  ansible.builtin.stat:
    path: /etc/radvd.conf.orig
  register: check_radvd_config

- name: "Backupdatei der radvd.conf Konfigurationsdatei erstellen."
  ansible.builtin.copy:
    remote_src: true
    src: /etc/radvd.conf
    dest: /etc/radvd.conf.orig
    owner: root
    group: root
    mode: '0644'
  when: not check_radvd_config.stat.exists

- name: "GUA _oder_ ULA: Generieren und kopieren der radvd Konfigurationsdatei /etc/radvd.conf"
  ansible.builtin.template:
    src: templates/radvd_single_config.j2
    dest: /etc/radvd.conf
    owner: root
    group: root
    mode: '0644'
  when: radvd_gua_mode == 'noone' or radvd_ula_mode == 'noone'

- name: "GUA _und_ULA: Generieren und kopieren der radvd Konfigurationsdatei /etc/radvd.conf"
  ansible.builtin.template:
    src: templates/radvd_both_config.j2
    dest: /etc/radvd.conf
    owner: root
    group: root
    mode: '0644'
  when: radvd_gua_mode != 'noone' and radvd_ula_mode != 'noone'

- name: "Restart des radvd zur Aktivierung der Konfiguration."
  ansible.builtin.systemd_service:
    name: radvd
    state: restarted
    # enabled: true
 
...

Bei der Konfiguration unseres radvd haben wir in unserem Konfigurationsbeispiel, ob nur eine GUA oder eine ULA oder eben beide Adresstypen genutzt werden sollen. Zusätzlich haben wir noch die Wahl ob eine IPv6 mit Hilfe von SLAAC oder Statful DHCPv6 bezogen werden soll.

Für die Überlegungen welche Adressen und wie diese bezogen werden, hilf unter anderem der Leitfaden für eine sichere IPv6-Netzwerkarchitektur vom Bundesamt für Sicherheit in der Informationstechnik.

Die Konfiguration welcher Adresstyp und ob SLAAC und|oder DHCPv6 zum Einsatz kommen wird, wird im Inventory mit den beiden Variablen radvd_gua_mode und radvd_ula_mode gesetzt:

GUA-/LUA-Mode bei IPv6-Adressen:

  • noone = weder SLAAC noch DHCPv6, keine Adresse
  • slaac = Adreese via SLAAC generieren
  • dhcp6 = Adresse via DHCPv6 beziehen

Um sicher zu stellen, dass die beiden Variablen radvd_gua_mode und radvd_ula_mode mit validen Daten gefüttert werden, überprüfen wir in einerm Task die Gültigkeit der Daten.

 $ vim roles/radvd/tasks/variablencheck.yml
roles/radvd/tasks/variablencheck.yml
---

- name: "Prüfen ob die Variable radvd_gua_mode gesetzt wurde."
  ansible.builtin.assert:
    that:
      - radvd_gua_mode is defined and (radvd_gua_mode == 'noone' or radvd_gua_mode == 'slaac' or radvd_gua_mode == 'dhcp6')
    fail_msg: "Die Variable radvd_gua_mode ist nicht vorhanden, leer, oder nicht noone, slaac oder dhcp6 !"
    quiet: true

- name: "Prüfen ob die Variable radvd_ula_mode gesetzt wurde."
  ansible.builtin.assert:
    that:
      - radvd_ula_mode is defined and (radvd_ula_mode == 'noone' or radvd_ula_mode == 'slaac' or radvd_ula_mode == 'dhcp6')
    fail_msg: "Die Variable radvd_ula_mode ist nicht vorhanden, leer, oder nicht noone, slaac oder dhcp6 !"
    quiet: true

- name: "Prüfen ob die beiden Variable raddv_gua_mode und radvd_ula_mode = noone sind."
  ansible.builtin.fail:
    fail_msg: "Die beiden Variable radvd_gua_mode und raddv_ula_mode können nicht beide noone sein !"
  when: radvd_gua_mode == 'noone' and radvd_ula_mode == 'noone'
 
...

Die Anpassung an unserer Firewall-Konfiguration erfolgt im Task firewalld.

 $ vim roles/radvd/tasks/firewalld.yml
roles/radvd/tasks/firewalld.yml
---

- name: "Sicherstellen, dass der Firewall-Daemon reboot(-fest) starten."
  ansible.builtin.systemd:
    state: reloaded
    enabled: true
    name: firewalld

- name: "Service basierte Rules je Zone definieren"
  ansible.posix.firewalld:
    zone: '{{ guest_zone_2 }}'
    service: dhcpv6
    immediate: true
    permanent: true
    state: enabled

- name: "Zum Schluss den aktuellen permanenten Regelsatz final neu laden."
  ansible.builtin.service:
    name: firewalld
    state: reloaded
 
...

Die beiden Templates radvd_single_config.j2 und radvd_both_config.j2 werden verwendet entsprechend der Auswahl ob nun Nur GUA oder ULA verwendet werden sollen oder beide. Das Template radvd_single_config.j2 für die Generierung der Konfigurationsdatei /etc/radvd.conf, wenn nur eine der beiden Adressarten gewählt wurde, hat folgenden Aufbau.

 $ vim roles/radvd/templates/radvd_single_config.j2
roles/radvd/templates/radvd_single_config.j2
# BEGIN ANSIBLE MANAGED - DO NOT EDIT BLOCK
# Ansible managed configuration file, do not modify manually!
#
# Configuration file for the router advertisement daemon radvd, 
# in which either GUA or ULA are distributed via SLAAC or DHCPv6,
# but not both! 
 
{% if (radvd_gua_mode == "dhcp6") or (radvd_ula_mode == "dhcp6") %}
#  - M-flag: AdvManagedFlag = on (address configuration via DHCPv6)
{% else %}
#  - M-flag: AdvManagedFlag = off (address configuration via SLAAC)
{% endif %}
#  - O-flag: AdvOtherConfigFlag = on (obtaining a DNS server list 
#            and a domain name from a Stateless DHCPv6 server, but
#            not addressing information.
{% if (radvd_gua_mode == "dhcp6") or (radvd_ula_mode == "dhcp6" )%}
#  - A-flag: AdvAutonomous = off (address configuration via DHCPv6)
{% else %}
#  - A-flag: AdvAutonomous = on (address configuration via SLAAC)
{% endif %}
 
interface {{ radvd_nic }}
{
  # A  flag  indicating  whether or not the router sends periodic
  # router advertisements and responds to router solicitations.
  # This option no longer has to be specified first, but it needs
  # to be on to enable advertisement on this interface.
  AdvSendAdvert on;
 
  # The  maximum  time  allowed between sending unsolicited multi-
  # cast router advertisements from the interface, in seconds.
  # Must be no less than 4 seconds and no greater than 1800 seconds.
  # Minimum when using Mobile IPv6 extensions: 0.07.
  # For values less than 0.2 seconds, 0.02 seconds is added to
  # account for scheduling granularities as specified in RFC3775.
  MaxRtrAdvInterval 600;
 
  # The minimum time allowed between sending unsolicited multicast
  # router advertisements from the interface, in seconds.
  # Must be no less than 3 seconds and no greater than
  # 0.75 * MaxRtrAdvInterval.
  # Minimum when using Mobile IPv6 extensions: 0.03.
  MinRtrAdvInterval 200;
 
  # The preference associated with the default router, as either
  # "low", "medium", or "high".
{% if radvd_gua_mode == "dhcp6" %}
  AdvDefaultPreference {{ radvd_gua_preference }};
{% else %}
  AdvDefaultPreference {{ radvd_ula_preference }};
{% endif %}
 
  # Mobile IPv6 support, when set, indicates that sending router is
  # able to serve as Mobile IPv6 Home Agent.
  # When set, minimum limits specified by Mobile IPv6 are used for
  # MinRtrAdvInterval and MaxRtrAdvInterval.
  AdvHomeAgentFlag off;
 
  # When set, hosts use the administered (stateful) protocol for
  # address  autoconfiguration in  addition to any addresses
  # autoconfigured using stateless address autoconfiguration.
  # The use of this flag is described in RFC 4862.
  # M-flag - if it is set to 1, this informs hosts that they can
  # obtain a global address as well as DNS and a domain name from
  # a Stateful DHCPv6 server. Typically this means that auto-
  # addressing using SLAAC is not allowed on this segment and both
  # the A-flag and the O-flag are set to 0.
{% if (radvd_gua_mode == "dhcp6") or (radvd_ula_mode == "dhcp6") %}
  AdvManagedFlag on;
{% else %}
  AdvManagedFlag off;
{% endif %}
 
  # When set, hosts use the administered (stateful) protocol for
  # autoconfiguration of other (non-address) information.
  # The use of this flag is described in RFC 4862
  # O-flag - if it is set to on, this informs hosts that they can
  # obtain a DNS server list and a domain name from a Stateless
  # DHCPv6 server, but not addressing information. Typically it
  # works in conjunction with SLAAC for auto-addressing and both
  # the A-flag and the O-flag are set to on.
  AdvOtherConfigFlag on;
 
  # The time, in milliseconds, that a node assumes a neighbor is
  # reachable after having received a reachability confirmation.
  # Used by the Neighbor Unreachability Detection algorithm (see
  # Section 7.3 of RFC 4861).
  # A value of zero means unspecified (by this router).
  # Must be no greater than 3,600,000 milliseconds (1 hour).
  AdvReachableTime 0;
 
  # The time,in milliseconds, between retransmitted Neighbor Soli-
  # citation messages. Used by address resolution and the Neighbor
  # Unreachability Detection algorithm (see Sections 7.2 and 7.3
  # of RFC 4861).  A value of zero means unspecified (by this router).
  AdvRetransTimer 0;
 
  # The default value that should be placed in the Hop Count field of
  # the IP header for outgoing (unicast) IP packets. The value should
  # be set to the current diameter of the Internet.
  # The value zero means unspecified (by this router).
  AdvCurHopLimit 64;
 
  # The lifetime associated with the default router in units of seconds.
  # The maximum value corresponds to 18.2 hours. A lifetime of 0 indi-
  # cates that the router is not a default router and should not appear
  # on the default router list. The router lifetime applies only to the
  # router´s usefulness as a default router; it does not apply to in-
  # formation contained in other message fields or options. Options that
  # need time limits for their information include their own lifetime
  # fields.
  # Must be either zero or between MaxRtrAdvInterval and 9000 seconds.
  # Default: 3 * MaxRtrAdvInterval (Minimum 1 second).
{% if radvd_gua_mode == "dhcp6" %}
  AdvDefaultLifetime {{ radvd_gua_route_time }};
{% else %}
  AdvDefaultLifetime {{ radvd_ula_route_time }};
{% endif %}
 
  # When set, the link-layer address of the outgoing interface is
  # included in the RA.
  AdvSourceLLAddress on;
 
{% if radvd_gua_mode == "dhcp6" or (radvd_gua_mode == "slaac") %}
  # global unified address prefix
  prefix {{ radvd_gua_prefix  }}{{  radvd_gua_netmask }}
{% else %}
  # unique local address prefix
  prefix {{ radvd_ula_prefix  }}{{  radvd_ula_netmask }}
{% endif %}
  {
    # When set, indicates that this prefix can be used for on-link
    # determination. When not set the advertisement makes no statement
    # about on-link or off-link properties of the prefix. For instance,
    # the prefix might be used for address configuration with some of
    # the addresses belonging to the prefix being on-link and others
    # being off-link.
    AdvOnLink on;
 
    # When set, indicates that this prefix can be used for autonomous
    # address configuration as specified in RFC 4862.
    # A-flag - if it is set to on, this informs hosts that they can
    # auto-generate GUA address using SLAAC. If it is set to off means
    # that auto-configuration is not allowed for this segment.
{% if (radvd_gua_mode == "dhcp6") or (radvd_ula_mode == "dhcp6") %}
    AdvAutonomous off;
{% else %}
    AdvAutonomous on;
{% endif %}
 
    # When set, indicates that the address of interface is sent instead
    # of network prefix, as is required by Mobile IPv6. When set,
    # minimum limits specified by Mobile IPv6 are used for
    # MinRtrAdvInterval and MaxRtrAdvInterval.
    AdvRouterAddr off;
 
    # The length of time in seconds (relative to the time the packet is
    # sent) that the prefix is valid for the purpose of on-link de-
    # termination. The symbolic value infinity represents infinity
    # (i.e. a value of all one bits (0xffffffff)). The valid lifetime
    # is also used by RFC 4862.
    #
    # Note that clients will ignore AdvValidLifetime of an existing
    # prefix if the lifetime is below two hours, as required in RFC
    # 4862 Section 5.5.3 point e).
    # Note: RFC4861's suggested default value is significantly longer:
    # 30 days. {% if radvd_gua_mode == "dhcp6" %}
 
    AdvValidLifetime {{ radvd_gua_valid_time  }};
{% else %}    
    AdvValidLifetime {{ radvd_ula_valid_time  }};
{% endif %}
 
    # The length of time in seconds (relative to the time the packet
    # is sent) that addresses generated from the prefix via stateless
    # address autoconfiguration remain preferred. The symbolic value
    # infinity represents infinity (i.e. a value of all one bits
    # (0xffffffff)).  See RFC 4862.
    #
    # Note: RFC4861's suggested default value is significantly longer:
    # 7 days. {% if radvd_gua_mode == "dhcp6" %}
 
    AdvPreferredLifetime {{ radvd_gua_prefd_time}};
{% else %}   
    AdvPreferredLifetime {{ radvd_ula_prefd_time}};
{% endif %}  };
 
{% if (radvd_gua_mode == "dhcp6") or (radvd_gua_mode == "slaac") %}
  # route for global scope address prefix
  route {{ radvd_gua_prefix  }}{{  radvd_gua_netmask }}
{% else %}
  # route for unique local address prefix
  prefix {{ radvd_ula_prefix  }}{{  radvd_ula_netmask }}
{% endif %}
  {
    # The preference associated with the default router, as either
    # "low", "medium", or "high".{% if (radvd_gua_mode == "dhcp6") or (radvd_gua_mode == "slaac") %}
 
    AdvRoutePreference {{ radvd_gua_preference }};
{% else %} 
 
    AdvRoutePreference {{ radvd_ula_preference }};
{% endif %}
 
    # The lifetime associated with the route in units of seconds. The
    # symbolic value infinity represents infinity (i.e. a value of
    # all one bits (0xffffffff)).
    #
    # Default: 3 * MaxRtrAdvInterval {% if (radvd_gua_mode == "dhcp6") or (radvd_gua_mode == "slaac") %}
 
    AdvRouteLifetime {{ radvd_gua_route_time }};
{% else %} 
 
    AdvRouteLifetime {{ radvd_ula_route_time }};
{% endif %}
  };
 
};
#
# END ANSIBLE MANAGED - DO NOT EDIT BLOCK

Sollen sowohl GUA wie ULA zum Einsatz kommen wird das zweite Template radvd_both_config.j2 herangezogen.

 $ vim roles/radvd/templates/radvd_both_config.j2
roles/radvd/templates/radvd_both_config.j2
# BEGIN ANSIBLE MANAGED - DO NOT EDIT BLOCK
# Ansible managed configuration file, do not modify manually!
#
# Configuration file for the router advertisement daemon radvd, 
# in which either GUA or ULA are distributed via SLAAC or DHCPv6.
 
 
#  - O-flag: AdvOtherConfigFlag = on (obtaining a DNS server list 
#            and a domain name from a Stateless DHCPv6 server, but
#            not addressing information.
#  SLAAC:
#  - A-flag: AdvAutonomous = on (address configuration via SLAAC)
#  - M-flag: AdvManagedFlag = off (address configuration via SLAAC)
#
#  DHCPv6:
#  - A-flag: AdvAutonomous = off (address configuration via DHCPv6)
#  - M-flag: AdvManagedFlag = on (address configuration via DHCPv6)
 
interface {{ radvd_nic }}
{
  # A  flag  indicating  whether or not the router sends periodic
  # router advertisements and responds to router solicitations.
  # This option no longer has to be specified first, but it needs
  # to be on to enable advertisement on this interface.
  AdvSendAdvert on;
 
  # The  maximum  time  allowed between sending unsolicited multi-
  # cast router advertisements from the interface, in seconds.
  # Must be no less than 4 seconds and no greater than 1800 seconds.
  # Minimum when using Mobile IPv6 extensions: 0.07.
  # For values less than 0.2 seconds, 0.02 seconds is added to
  # account for scheduling granularities as specified in RFC3775.
  MaxRtrAdvInterval 600;
 
  # The minimum time allowed between sending unsolicited multicast
  # router advertisements from the interface, in seconds.
  # Must be no less than 3 seconds and no greater than
  # 0.75 * MaxRtrAdvInterval.
  # Minimum when using Mobile IPv6 extensions: 0.03.
  MinRtrAdvInterval 200;
 
  # The preference associated with the default router, as either
  # "low", "medium", or "high".
  AdvDefaultPreference {{ radvd_gua_preference }};
 
  # Mobile IPv6 support, when set, indicates that sending router is
  # able to serve as Mobile IPv6 Home Agent.
  # When set, minimum limits specified by Mobile IPv6 are used for
  # MinRtrAdvInterval and MaxRtrAdvInterval.
  AdvHomeAgentFlag off;
 
  # When set, hosts use the administered (stateful) protocol for
  # address  autoconfiguration in  addition to any addresses
  # autoconfigured using stateless address autoconfiguration.
  # The use of this flag is described in RFC 4862.
  # M-flag - if it is set to 1, this informs hosts that they can
  # obtain a global address as well as DNS and a domain name from
  # a Stateful DHCPv6 server. Typically this means that auto-
  # addressing using SLAAC is not allowed on this segment and both
  # the A-flag and the O-flag are set to 0.
{% if (radvd_gua_mode == "dhcp6") %}
  AdvManagedFlag on;
{% else %}
  AdvManagedFlag off;
{% endif %}
 
  # When set, hosts use the administered (stateful) protocol for
  # autoconfiguration of other (non-address) information.
  # The use of this flag is described in RFC 4862
  # O-flag - if it is set to on, this informs hosts that they can
  # obtain a DNS server list and a domain name from a Stateless
  # DHCPv6 server, but not addressing information. Typically it
  # works in conjunction with SLAAC for auto-addressing and both
  # the A-flag and the O-flag are set to on.
  AdvOtherConfigFlag on;
 
  # The time, in milliseconds, that a node assumes a neighbor is
  # reachable after having received a reachability confirmation.
  # Used by the Neighbor Unreachability Detection algorithm (see
  # Section 7.3 of RFC 4861).
  # A value of zero means unspecified (by this router).
  # Must be no greater than 3,600,000 milliseconds (1 hour).
  AdvReachableTime 0;
 
  # The time,in milliseconds, between retransmitted Neighbor Soli-
  # citation messages. Used by address resolution and the Neighbor
  # Unreachability Detection algorithm (see Sections 7.2 and 7.3
  # of RFC 4861).  A value of zero means unspecified (by this router).
  AdvRetransTimer 0;
 
  # The default value that should be placed in the Hop Count field of
  # the IP header for outgoing (unicast) IP packets. The value should
  # be set to the current diameter of the Internet.
  # The value zero means unspecified (by this router).
  AdvCurHopLimit 64;
 
  # The lifetime associated with the default router in units of seconds.
  # The maximum value corresponds to 18.2 hours. A lifetime of 0 indi-
  # cates that the router is not a default router and should not appear
  # on the default router list. The router lifetime applies only to the
  # router´s usefulness as a default router; it does not apply to in-
  # formation contained in other message fields or options. Options that
  # need time limits for their information include their own lifetime
  # fields.
  # Must be either zero or between MaxRtrAdvInterval and 9000 seconds.
  # Default: 3 * MaxRtrAdvInterval (Minimum 1 second).
  AdvDefaultLifetime {{ radvd_gua_route_time }};
 
  # When set, the link-layer address of the outgoing interface is
  # included in the RA.
  AdvSourceLLAddress on;
 
  # global unified address prefix
  prefix {{ radvd_gua_prefix  }}{{  radvd_gua_netmask }}
  {
    # When set, indicates that this prefix can be used for on-link
    # determination. When not set the advertisement makes no statement
    # about on-link or off-link properties of the prefix. For instance,
    # the prefix might be used for address configuration with some of
    # the addresses belonging to the prefix being on-link and others
    # being off-link.
    AdvOnLink on;
 
    # When set, indicates that this prefix can be used for autonomous
    # address configuration as specified in RFC 4862.
    # A-flag - if it is set to on, this informs hosts that they can
    # auto-generate GUA address using SLAAC. If it is set to off means
    # that auto-configuration is not allowed for this segment.
{% if (radvd_gua_mode == "dhcp6") %}
    AdvAutonomous off;
{% else %}
    AdvAutonomous on;
{% endif %}
 
    # When set, indicates that the address of interface is sent instead
    # of network prefix, as is required by Mobile IPv6. When set,
    # minimum limits specified by Mobile IPv6 are used for
    # MinRtrAdvInterval and MaxRtrAdvInterval.
    AdvRouterAddr off;
 
    # The length of time in seconds (relative to the time the packet is
    # sent) that the prefix is valid for the purpose of on-link de-
    # termination. The symbolic value infinity represents infinity
    # (i.e. a value of all one bits (0xffffffff)). The valid lifetime
    # is also used by RFC 4862.
    #
    # Note that clients will ignore AdvValidLifetime of an existing
    # prefix if the lifetime is below two hours, as required in RFC
    # 4862 Section 5.5.3 point e).
    # Note: RFC4861's suggested default value is significantly longer:
    # 30 days.
    AdvValidLifetime {{ radvd_gua_valid_time  }};
 
    # The length of time in seconds (relative to the time the packet
    # is sent) that addresses generated from the prefix via stateless
    # address autoconfiguration remain preferred. The symbolic value
    # infinity represents infinity (i.e. a value of all one bits
    # (0xffffffff)).  See RFC 4862.
    #
    # Note: RFC4861's suggested default value is significantly longer:
    # 7 days.i
    AdvPreferredLifetime {{ radvd_gua_prefd_time}};
  };
 
  # route for global scope address prefix
  route {{ radvd_gua_prefix  }}{{  radvd_gua_netmask }}
  {
    # The preference associated with the default router, as either
    # "low", "medium", or "high".
    AdvRoutePreference {{ radvd_gua_preference }};
 
    # The lifetime associated with the route in units of seconds. The
    # symbolic value infinity represents infinity (i.e. a value of
    # all one bits (0xffffffff)).
    #
    # Default: 3 * MaxRtrAdvInterval
    AdvRouteLifetime {{ radvd_gua_route_time }};
  };
 
  # unique local address prefix
  prefix {{ radvd_ula_prefix  }}{{  radvd_gua_netmask }}
 {
    # When set, indicates that this prefix can be used for on-link
    # determination. When not set the advertisement makes no statement
    # about on-link or off-link properties of the prefix. For instance,
    # the prefix might be used for address configuration with some of
    # the addresses belonging to the prefix being on-link and others
    # being off-link.
    AdvOnLink on;
 
    # When set, indicates that this prefix can be used for autonomous
    # address configuration as specified in RFC 4862.
    # A-flag - if it is set to on, this informs hosts that they can
    # auto-generate GUA address using SLAAC. If it is set to off means
    # that auto-configuration is not allowed for this segment.
{% if radvd_ula_mode == "dhcp6" %}
    AdvAutonomous off;
{% else %}
    AdvAutonomous on;
{% endif %}
 
    # When set, indicates that the address of interface is sent instead
    # of network prefix, as is required by Mobile IPv6. When set,
    # minimum limits specified by Mobile IPv6 are used for
    # MinRtrAdvInterval and MaxRtrAdvInterval.
    AdvRouterAddr off;
 
    # The length of time in seconds (relative to the time the packet is
    # sent) that the prefix is valid for the purpose of on-link de-
    # termination. The symbolic value infinity represents infinity
    # (i.e. a value of all one bits (0xffffffff)). The valid lifetime
    # is also used by RFC 4862.
    #
    # Note that clients will ignore AdvValidLifetime of an existing
    # prefix if the lifetime is below two hours, as required in RFC
    # 4862 Section 5.5.3 point e).
    # Note: RFC4861's suggested default value is significantly longer:
    # 30 days.
    AdvValidLifetime {{ radvd_ula_valid_time  }};
 
    # The length of time in seconds (relative to the time the packet
    # is sent) that addresses generated from the prefix via stateless
    # address autoconfiguration remain preferred. The symbolic value
    # infinity represents infinity (i.e. a value of all one bits
    # (0xffffffff)).  See RFC 4862.
    #
    # Note: RFC4861's suggested default value is significantly longer:                                                                                             
    # 7 days.
    AdvPreferredLifetime {{ radvd_ula_prefd_time}};
  };
 
  # route for global scope address prefix
  route {{ radvd_ula_prefix  }}{{  radvd_ula_netmask }}
  {
    # The preference associated with the default router, as either
    # "low", "medium", or "high".
    AdvRoutePreference {{ radvd_ula_preference }};
 
    # The lifetime associated with the route in units of seconds. The
    # symbolic value infinity represents infinity (i.e. a value of
    # all one bits (0xffffffff)).
    #
    # Default: 3 * MaxRtrAdvInterval
    AdvRouteLifetime {{ radvd_ula_route_time }};
  };
 
};
#
# END ANSIBLE MANAGED - DO NOT EDIT BLOCK

Ausführung - Playbooklauf

Die orchestrierte Variante der Installation und Konfiguration unseres radvd-Daemon gestaltet sich ab sofort sehr einfach, brauchen wir doch lediglich die Konfigurationswerte im Inventory zu hinterlegen und zu pflegen und letztendlich das Playbook entsprechend aufzurufen:

 $ ansible-playbook playbooks/arch_radvd.yml

[22:15:26] Gathering Facts
↳  vml010110 | SUCCESS | 1.98s
[22:15:28] radvd : Installation und Konfiguration des Router Advertisement Daemon radvd.
↳  vml010110 | SUCCESS | 12ms
[22:15:28]     ↳ install: Installation des Router Advertisement Daemon radvd.
↳  vml010110 | CHANGED | 3.14s
[22:15:31]     ↳ install: Checken ob es bereits eine Backupdatei der radvd.conf gibt.
↳  vml010110 | SUCCESS | 654ms
[22:15:32]     ↳ install: Backupdatei der radvd.conf Konfigurationsdatei erstellen.
↳  vml010110 | CHANGED | 705s
[22:15:32]     ↳ install: Generieren und kopieren der radvd Konfigurationsdatei /etc/radvd.conf
↳  vml010110 | CHANGED | 1.13s
[22:15:34] radvd : Konfiguration des firewalld für den Router Advertisement Daemon radvd.
↳  vml010110 | SUCCESS | 17ms
[22:15:34]     ↳ firewalld: Sicherstellen, dass der Firewall-Daemon reboot(-fest) starten.
↳  vml010110 | CHANGED | 1.40s
[22:15:35]     ↳ firewalld: Service basierte Rules je Zone definieren.
↳  vml010110 | SUCCESS | 872ms
[22:15:36]     ↳ firewalld: Zum Schluss den aktuellen permanenten Regelsatz final neu laden.
↳  vml010110 | CHANGED | 928ms
[22:15:37] system
-- Play recap --
vml010110                  : ok=10   changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

FIXME

Ergebniskontrolle

Nun prüfen wir, ob unser radvd auch die richtigen Router Advertisement ICMPv6 Nachrichten ins Netz schickt. Hier bieten sich zwei mögliche Varianten an:

  1. Mit dem Programm radvdump aus dem Paket radvd. Hierzu starten wir dias besagte Binary auf einem unserer Clients im lokalen Netzwerk-Segment dieses Binary.
     # radvdump
    #
    # radvd configuration generated by radvdump 2.18
    # based on Router Advertisement from fe80::10:ff:fe10:110
    # received by interface enp0s25
    #
    
    interface enp0s25
    {
    	AdvSendAdvert on;
    	# Note: {Min,Max}RtrAdvInterval cannot be obtained with radvdump
    	AdvManagedFlag on;
    	AdvOtherConfigFlag on;
    	AdvReachableTime 0;
    	AdvRetransTimer 0;
    	AdvCurHopLimit 64;
    	AdvDefaultLifetime 1800;
    	AdvHomeAgentFlag off;
    	AdvDefaultPreference medium;
    	AdvSourceLLAddress on;
    
    	prefix 2001:a:bcd:1234::/64
    	{
    		AdvValidLifetime 5400;
    		AdvPreferredLifetime 2700;
    		AdvOnLink on;
    		AdvAutonomous off;
    		AdvRouterAddr off;
    	}; # End of prefix definition
    
    
    	prefix fdb6:cb48:9d77::/64
    	{
    		AdvValidLifetime 5400;
    		AdvPreferredLifetime 2700;
    		AdvOnLink on;
    		AdvAutonomous off;
    		AdvRouterAddr off;
    	}; # End of prefix definition
    
    
    	route 2001:a:bcd:1234::/64
    	{
    		AdvRoutePreference medium;
    		AdvRouteLifetime 1800;
    	}; # End of route definition
    
    
    	route fdb6:cb48:9d77::/64
    	{
    		AdvRoutePreference medium;
    		AdvRouteLifetime 1800;
    	}; # End of route definition
    
    }; # End of interface definition

    In regelmäßigen Abständen tauchen also diese RA-Meldungen auf.

  2. Mit Hilfe von tcpdump können wir auch die RA-Meldungen mitschneiden und darstellen, in nachfolgenden Beispiel ist der Name des Netzwerkinterfaces enp0s25.
     # tcpdump -vi enp0s25 "icmp6[icmp6type] == icmp6-routeradvert"
    cpdump: listening on enp0s25, link-type EN10MB (Ethernet), snapshot length 262144 bytes
    22:23:42.141271 IP6 (flowlabel 0xc155a, hlim 255, next-header ICMPv6 (58) payload length: 136) _gateway > nitropad: [icmp6 sum ok] ICMP6, router advertisement, length 136
    	hop limit 64, Flags [managed, other stateful], pref medium, router lifetime 1800s, reachable time 0ms, retrans timer 0ms
    	  prefix info option (3), length 32 (4): 2001:a:bcd:1234::/64, Flags [onlink], valid time 5400s, pref. time 2700s
    	  prefix info option (3), length 32 (4): fdb6:cb48:9d77::/64, Flags [onlink], valid time 5400s, pref. time 2700s
    	  route info option (24), length 24 (3):  2001:a:bcd:1234::/64, pref=medium, lifetime=1800s
    	  route info option (24), length 24 (3):  fdb6:cb48:9d77::/64, pref=medium, lifetime=1800s
    	  source link-address option (1), length 8 (1): 52:54:00:41:11:02
    
    ^C
    1 packet captured
    1 packet received by filter
    0 packets dropped by kernel

Links


1)
Stateless Address Autoconfiguration
2)
Duplicate Address Detection
3)
Link Local Address
4)
Router Solicitation
5)
Unique Local Address
6)
Global Unicast Address
Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
  • linux/radvd.txt
  • Zuletzt geändert: 06.07.2024 20:30.
  • von django