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.:
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.
Nachfolgendes Schaubild fasst den grundlegenden Ablauf zusammen:
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.
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.
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.e
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
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
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:
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:
Werfen wir nun noch einen Blick auf die einzelnen Schritte:
FE80::/64
und der EUI-64-Schnittstellenkennung, welche er aus der MAC-Adresse der Netzwerkkarte/WLAN-Adapter generiert, eine entsprechende Adresse erzeugen. 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
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. 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. 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:
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.
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:
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.off
(Adresskonfiguration über SLAAC)on
(Abrufen einer DNS-Serverliste und einen Domain-Namen von einem Stateless DHCPv6-Server, aber keine keine Adressierungsinformationen. on
(Adresskonfiguration über SLAAC)2001:a:bcd:1234
2001:a:bcd:1234::/64
und eine Gültigkeit von einer 1/2 Stunde, also 1800
Sekunden.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
# 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:
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.
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ß!
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-Rechner 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
# 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
# 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!
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:
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.on
(Adresskonfiguration via Stateful DHCPv6)on
(Abrufen einer DNS-Serverliste und einen Domain-Namen von einem Stateless DHCPv6-Server, aber keine keine Adressierungsinformationen. off
(Adresskonfiguration via Statful DHCPv6)2001:a:bcd:1234
: 2001:a:bcd:1234::/64
und eine Gültigkeit von einer 1/2 Stunde, also 1800
Sekunden.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
# 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:
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.
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!
In den beiden vorgenannten Konfigurationsbeispielen Konfigurationsbeispiel für SLAAC und Konfigurationsbeispiel DHCPv6 haben wir gesehen, dass wir mit den M
- und A
-Flag steuern können, wie ein Client, wenn er sich mit unserem Netzwerk verbindet, zu einer oder mehreren IP-v6-Adressen kommen kann. Auch da Thema SLAAC und Privacy Extension bei de Konfiguration der (Arch Linux) Clients haben wir uns im Detail vorgenommen.
Wenn wir uns mit dem Thema IPv6 im Intranet befassen, wird sich in aller Regel folgende Frage stellen: Welche Typen von Adressen werden benötigt und welche sollen letztendlich auch wirklich genutzt werden. Nun Gut, die Link Locla Address generiert ein Host selbst wie wir bereits wissen, denn ohne diese könnte er z.B. kein SLAAC initiieren.
Betrachten wir also nun die Unified Local Address, können wir erkennen, dass mit Hilfe dieser Adressen z.B. ein Laptop den Drucker im Netz direkt erreichen kann, denn wollen wir unserem Drucker eine öffentliche IP-Adresse verpassen? Nein, sicherlich nicht! Ausserdem soll es ja unter anderem ISP7) geben, die ihren Kunden mit Hinweis von Privatsphäre keine statischen /56
oder /64
zuweisen sondern lediglich dynamische Prefixe, die sich bei jeder Neueinwahl oder auch 1x Pro Tag ändern. Würde man mit Hilfe von Prefix-Delegation nun diesen vom ISP zugewiesenen dynamischen Prefix im Intranet weiterverwenden wollen, würde sich in unserem Beispiel auch jedes mal die GUA des Drucker ändern - welch gruselige Vorstellung und administrativ kaum handelbar! Gar nicht toll, gar nicht schön … Moment, da war doch noch so ein Thema, statische feste IPv6 GUA: Wie wir beim Abschnitt SLAAC und privacy extension bereits bemerkt haben, können einzelnen Nutzer mit ihren Geräten anhand der letzten 48 Bits der IPv6-Adresse weltweit trackbar werden. Nun Gut unter SLAAC gibt es die Option privacy extension, in den RFCs zu DHCPv6 sucht man aber leider vergebens nach einer derartigen Option - O.K. zumindest im Jahre 2024 noch! Als sind statische eineindeutige GUA im Intranet eigentlich auch nichts was man sehen und haben möchte!
Je länger man sich nun mit der ganzen Thematik um nicht Misere zu sagen beschäftigt kommt man zu folgender Musterkonfigurationslösung:
Wir wollen uns also nun ansehen, wie wir solch ein Muster-Szenario abbilden können
Der geneigte Leser wir sich nun fragen, ja wie macht man denn nun das beim radvd? Denn schliesslich wissen wir ja dass wir bei Nutzung von SLAAC die bekannten Flags wir folgt setzen müssen:
off
(Adresskonfiguration über SLAAC)on
(Abrufen einer DNS-Serverliste und einen Domain-Namen von einem Stateless DHCPv6-Server, aber keine keine Adressierungsinformationen. on
(Adresskonfiguration über SLAAC)Hingegen bei DHCPv6 hingegen müssen wir die Flags wie folgt setzen.
on
(Adresskonfiguration via Stateful DHCPv6)on
(Abrufen einer DNS-Serverliste und einen Domain-Namen von einem Stateless DHCPv6-Server, aber keine keine Adressierungsinformationen. off
(Adresskonfiguration via Stateful DHCPv6)
O.K. das O
-Flag macht uns keine Sorgen, das setzen wir ja immer auf on
. Das A-Flag wird über die Konfigurationsoption AdvAutonomous
entweder auf on
bei SLAAC gesetzt und auf off
bei DHCPv6. Da diese Option im jeweiligen Prefix-Abschnitt in der Konfigurationsdatei radvd.conf
definiert wird, ist das auch keine allzu grosse Herausforderung. O.K. was bleibt übrig? Richtig, das M
-Flag, welches bei SLAAC mit der Konfigurationsoption AdvManagedFlag
auf off
gesetzt werden muss und bei DHCPv6 eben auf on
. Tja aber leider ist die Konfigurationsoption AdvManagedFlag
global in der Konfigurationsdatei radvd.conf
, sie kann also nur 1x definiert werden und leider nicht 2-mal wie wir es eigentlich bräuchten!
Wie wir aber dennoch eine funktionierende Konfiguration des radvd hierzu hinbekommen werden wir uns nun ansehen. SPOILER: Ja die Konfiguration läuft wirklich uns wurde in fast Tagelangen nein Nächtelangen triel-and-error Runden mehrfach validiert1 In unserem Konfigurationsbeispiel gehen wir von folgenden Rahmenbedingungen aus:
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ässig seine Router Advertisements ICMPv6-Nachrichten an alle Clients im lokalen betreffenden Netz.2001:a:bcd:1234
2001:a:bcd:1234::/64
1800
Sekunden.off
(Adresskonfiguration über SLAAC)on
(Abrufen einer DNS-Serverliste und einen Domain-Namen von einem Stateless DHCPv6-Server, aber keine keine Adressierungsinformationen. on
(Adresskonfiguration über SLAAC)eth1
des radvd-/kea-dhcp6-Host 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.fdb6:cb48:9d77:0::/64
.fdb6:cb48:9d77:0::/64
1800
Sekunden.1
AdvManagedFlag = on
(Adresskonfiguration via Stateful DHCPv6) setzen. Wir haben aber bereits bemerkt dass wir diese globale Option in der radvd.conf nur einmal setzen können - wir ignorieren also geflissentlich diese Option bei der ULA und DHCPv6 on
(Abrufen einer DNS-Serverliste und einen Domain-Namen von einem Stateless DHCPv6-Server, aber keine keine Adressierungsinformationen. off
(Adresskonfiguration via Stateful DHCPv6)Daraus ergibt sich nun folgende Konfigurationsdatei für unseren radvd:
# vim /etc/radvd.conf
# Configuration example for the router advertisement daemon radvd # for GUA and SLAAC as well as ULA with DHCPv6 # # - O-flag: AdvOtherConfigFlag = on (obtaining a DNS server list # and a domain name from a Stateless DHCPv6 server, but # not addressing information. # - M-flag: AdvManagedFlag = off (address configuration via SLAAC for GUA) # - A-flag: AdvAutonomous = on (address configuration via SLAAC for GUA) # - A-flag: AdvAutonomous = off (address configuration via DHCPv6 for static ULA) 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 2003:a:e0d:7607::/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 2003:a:e0d:7607::/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; }; 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 entspprechend 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
[Jul 09 17:59:05] radvd (1264): 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
Jul 09 18:00:37 vml000110 systemd[1]: Started IPv6 Router Advertisement Daemon. Jul 09 18:00:37 vml000110 radvd[1296]: [Jul 09 18:00:37] radvd (1296): 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 Tue 2024-07-09 18:00:37 CEST; 1min 19s ago Invocation: bc40f348d21e45bf83b5976494e7fe39 Main PID: 1296 (radvd) Tasks: 2 (limit: 9510) Memory: 368K (peak: 1.5M) CPU: 13ms CGroup: /system.slice/radvd.service ├─1296 /usr/bin/radvd --nodaemon └─1297 /usr/bin/radvd --nodaemon Jul 09 18:00:37 vml000110 systemd[1]: Started IPv6 Router Advertisement Daemon. Jul 09 18:00:37 vml000110 radvd[1296]: [Jul 09 18:00:37] radvd (1296): 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:
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 on; 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.
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:08:04.399616 IP6 (flowlabel 0x37bf6, hlim 255, next-header ICMPv6 (58) payload length: 136) _gateway > nitropad: [icmp6 sum ok] ICMP6, router adver 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): 2003:a:e0d:7607::/64, Flags [onlink, auto], 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): 2003:a:e0d:7607::/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
Wir brauchen jetzt natürlich für die statischen ULA noch eine passende Konfigurationsdatei. Wir greifen nun kurz dem Kapitel DHCPv4/v6-Server mit DHCP ISC Kea unter Arch Linux einrichten und nutzen vor und werfen einen kurzen Blick auf die unkommentierte Konfigurationsdatei /etc/kea/kea-dhcp6.conf
des kea-dhcp6-Daemon. Im besagten Kapitel werden wir uns noch mit dem DHCP ISC Kea ähnlich detailliert auseinander setzen wir hier in diesem Kapitel Router Advertisements mit radvd unter Arch Linux einrichten und nutzen!
# vim /etc/kea/kea-dhcp6.conf
Fragen wir die IP-Adresse des Netzwerkinterfaces ab sehen wir:
django@nitropad:~$ ip addr show enp0s25
2: enp0s25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 3c:97:0e:18:e4:dd brd ff:ff:ff:ff:ff:ff inet 10.0.10.73/24 brd 10.0.10.255 scope global dynamic noprefixroute enp0s25 valid_lft 3594sec preferred_lft 3594sec inet6 fdb6:cb48:9d77:10:0:10:73/128 scope global dynamic noprefixroute valid_lft 3995sec preferred_lft 2995sec inet6 2001:a:bcd:1234:c79d:9c68:ff37:3f53/64 scope global temporary dynamic valid_lft 5395sec preferred_lft 2695sec inet6 2001:a:bcd:1234:2688:fdb0:775:c02c/64 scope global dynamic mngtmpaddr noprefixroute valid_lft 5395sec preferred_lft 2695sec inet6 fe80::e9a6:bb03:1544:b000/64 scope link noprefixroute valid_lft forever preferred_lft forever
Wir haben neben der IPv4 Adresse 10.0.10.73
und der vom Client-System generierten LLA fe80::e9a6:bb03:1544:b000/64
mit *scope link noprefixroute
noch drei weitere IPv6-Adressen erhalten. Das wäre zum einen die statische feste ULA fdb6:cb48:9d77:10:0:10:73/128
mit scope global dynamic noprefixrout
noch eine stabile dynamische IPv6 Adresse 2001:a:bcd:1234:2688:fdb0:775:c02c/64
mit scope global dynamic mngtmpaddr
und eine temporäre „privacy“ IPv6 Adresse 2001:a:bcd:1234:c79d:9c68:ff37:3f53/64
mit 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.
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.
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
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
Unser Playbook zum Installieren und Konfigurieren unseres Router Advertisement Daemon radvd, ist unscheinbar und unspektakulär.
$ vim 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 ...
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/
Wie wir sehen ist die Rolle durchaus überschaubar, im Task main.yaml
verweisen wir lediglich auf die eigentlichen Tasks variablencheck
, install.yml
und firewalld.yml
$ vim 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 ...
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 Adresseslaac
= Adresse via SLAAC generierendhcp6
= 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 einem Task die Gültigkeit der Daten.
$ vim 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 eigentliche Installation und Konfiguration erfolgt dann im Task install.yml
.
$ vim 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 ...
Die Anpassung an unserer Firewall-Konfiguration erfolgt im Task firewalld
.
$ vim 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
# 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
# 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
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
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:
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.
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