# Configuration réseau 100% systemd avec Debian GNU/Linux
[toc]
---
## Scénario
Dans le but de faire évoluer les images de machines virtuelles, on souhaite utiliser une configuration réseau totalement pilotée par **systemd**.
L'objectif est de bénéficier d'une configuration *moderne* totalement unifiée et indépendante de la distribution Lunux utilisée.
Cette évolution de la configuration réseau porte sur 3 parties :
1. Le pilotage de l'interface réseau
2. La résolution des noms de domaines avec le protocole DNS (*Domain Name System*)
3. La synchronisation de l'horloge avec le protocole NTP (*Network Time Protocol*)
## L'interface réseau
La configuration des interfaces réseau est assurée par le paquet **ifupdown** sur la distribution Debian GNU/Linux depuis l'origine.
C'est le fichier `/etc/network/interfaces` qui contient les instructions de configuration.
Avec une solution **systemd** complète, c'est le paquet **systemd-networkd** qui remplace **ifupdown**.
Avec ce nouveau code de pilotage, il faut créer un nouveau fichier de configuration : `/etc/systemd/network/10-vm-default.network`.
### Q1	 Quel est le nom de l'interface réseau de la machine virtuelle ?
On dispose de plusieurs sources d'information.
1. Liste des interfaces avec la commande `ip` :
On repère le nom `enp0s1` dans la liste ci-dessous.
```bash
ip addr ls
```
```=
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether b8:ad:ca:fe:00:00 brd ff:ff:ff:ff:ff:ff
inet 198.18.69.0/23 brd 198.18.69.255 scope global dynamic enp0s1
valid_lft 85140sec preferred_lft 85140sec
inet6 2001:678:3fc:44:baad:caff:fefe:0/64 scope global dynamic mngtmpaddr proto kernel_ra
valid_lft 85838sec preferred_lft 13838sec
inet6 fe80::baad:caff:fefe:0/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
```
2. La commande `udevadm` donne le résultat de la traduction du nom des périphériques réseau en parcourant le dossier `/sys/class/net/`
On obtient le même résultat : `enp0s1`.
```bash
udevadm info --path /sys/class/net/enp0s1
```
```=
P: /devices/pci0000:00/0000:00:01.0/virtio0/net/enp0s1
M: enp0s1
R: 1
U: net
I: 2
```
### Q2	 Quelles sont les instructions de configuration réseau données aux scripts du paquet `ifupdown` ?
On affiche le contenu du fichier `/etc/network/interfaces`pour connaître la liste des directives de configuration.
```bash
cat /etc/network/interfaces
```
```=
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
allow-hotplug enp0s1
iface enp0s1 inet dhcp
# This is an autoconfigured IPv6 interface
iface enp0s1 inet6 auto
```
Ces instructions correspondent à un adressage automatique de l'interface `enp0s1`.
* Pour IPv4, on utilise un client DHCP (*Dynamic Host Control Protocol*)
* Pour IPv6, on utilise la fonction d'adressage SLAAC (*Stateless Address Auto Configuration*)
### Q3	 Quel est l'état du service `systemd-networkd` ?
Le gestionnaire d'initialisation **systemd** fournit un service spécifique pour le pilotage des interfaces réseau : `systemd-networkd`.
On consulte le statut du service et on constate qu'il est désactivé.
```bash
systemctl status systemd-networkd
```
```=
○ systemd-networkd.service - Network Configuration
Loaded: loaded (/lib/systemd/system/systemd-networkd.service; disabled; preset: enabled)
Active: inactive (dead)
TriggeredBy: ○ systemd-networkd.socket
Docs: man:systemd-networkd.service(8)
man:org.freedesktop.network1(5)
FD Store: 0 (limit: 512)
```
C'est la ligne 3 qui indique l'état du service : `inactive`.
### Q4	 Quelles sont les nouvelles instructions de configuration réseau à mettre en place ?
On doit créer un nouveau fichier de configuration pour chaque interface à prendre en charge.
1. Interface de boucle locale `lo`
On nomme le fichier de configuration `/etc/systemd/network/01-lo.network`.
```bash
cat << EOF | sudo tee /etc/systemd/network/01-lo.network
[Match]
Name=lo
[Network]
LinkLocalAddressing=ipv6
Address=127.0.0.1/8
EOF
```
2. Interface Ethernet `enp0s1`
On nomme le fichier de configuration `/etc/systemd/network/10-vm-default.network`.
Le jeu d'instructions reprend les demandes d'adressage automatique pour IPv4 et IPv6.
```bash
cat << EOF | sudo tee /etc/systemd/network/10-vm-default.network
[Match]
Name=enp0s1
[Network]
MulticastDNS=yes
DHCP=ipv4
[DHCP]
UseDNS=yes
[IPv6AcceptRA]
UseDNS=yes
EOF
```
### Q5	 Comment activer le service `systemd-networkd` ?
Comme il s'agit d'un service **systemd**, on fait appel à la commande `systemctl`.
```bash
sudo systemctl enable systemd-networkd
```
### Q6	 Comment finaliser la nouvelle gestion des interfaces réseau ?
L'étape précédente d'activation du service `systemd-networkd` ne suffit pas à rendre la gestion de configuration des interfaces réseau effective.
Pour finaliser le changement de pilotage, on doit **supprimer le paquet ifupdown** pour éviter les conflits dans la prise en charge des interfaces.
```bash
sudo apt purge ifupdown
```
Enfin, on peut relancer la machine virtuelle et vérifier que les directives de configuration de l'interface réseau ont bien été exécutées.
### Q7	 Comment visualiser l'état de la configuration réseau ?
On dispose de plusieurs solutions pour répondre à cette question.
* La commande `ip` est certainement le moyen le plus immédiat d'accéder aux informations sur la configuration réseau.
On commence par la liste des adresses qui montre que l'interface `enp0s1`a bien obtenu les adresses de couche réseau IPv4 et IPv6.
```bash
ip addr ls
```
```=
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether b8:ad:ca:fe:00:00 brd ff:ff:ff:ff:ff:ff
inet 198.18.69.0/23 metric 1024 brd 198.18.69.255 scope global dynamic enp0s1
valid_lft 86007sec preferred_lft 86007sec
inet6 2001:678:3fc:44:baad:caff:fefe:0/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 86195sec preferred_lft 14195sec
inet6 fe80::baad:caff:fefe:0/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
```
On complète avec les tables de routage qui montrent qu'une adresse de passerelle par défaut est en place pour IPv4 et pour IPv6.
Dans les deux cas c'est le mot clé `default` qu'il faut rechercher.
```bash
ip route ls
```
```=
default via 198.18.68.1 dev enp0s1 proto dhcp src 198.18.69.0 metric 1024
172.16.0.2 via 198.18.68.1 dev enp0s1 proto dhcp src 198.18.69.0 metric 1024
198.18.68.0/23 dev enp0s1 proto kernel scope link src 198.18.69.0 metric 1024
198.18.68.1 dev enp0s1 proto dhcp scope link src 198.18.69.0 metric 1024
```
```bash
ip -6 route ls
```
```=
2001:678:3fc:44::/64 dev enp0s1 proto ra metric 1024 expires 86099sec pref medium
fe80::/64 dev enp0s1 proto kernel metric 256 pref medium
default via fe80::9803:fff:fe68:ea4a dev enp0s1 proto ra metric 1024 expires 1499sec pref medium
```
* Comme on a activé un service piloté par **systemd**, il est logique de s'intéresser à l'état de ce service.
```bash
systemctl status systemd-networkd
```
```=
● systemd-networkd.service - Network Configuration
Loaded: loaded (/lib/systemd/system/systemd-networkd.service; enabled; preset: enabled)
Active: active (running) since Fri 2023-12-08 09:23:51 CET; 43min left
TriggeredBy: ● systemd-networkd.socket
Docs: man:systemd-networkd.service(8)
man:org.freedesktop.network1(5)
Main PID: 483 (systemd-network)
Status: "Processing requests..."
Tasks: 1 (limit: 1079)
FD Store: 0 (limit: 512)
Memory: 3.3M
CPU: 94ms
CGroup: /system.slice/systemd-networkd.service
└─483 /lib/systemd/systemd-networkd
déc. 08 09:23:51 vm0 systemd-networkd[483]: lo: Link UP
déc. 08 09:23:51 vm0 systemd-networkd[483]: lo: Gained carrier
déc. 08 09:23:51 vm0 systemd-networkd[483]: Enumeration completed
déc. 08 09:23:51 vm0 systemd[1]: Started systemd-networkd.service - Network Configuration.
déc. 08 09:23:51 vm0 systemd-networkd[483]: enp0s1: Configuring with /etc/systemd/network/10-vm-default.network.
déc. 08 09:23:51 vm0 systemd-networkd[483]: enp0s1: Link UP
déc. 08 09:23:51 vm0 systemd-networkd[483]: enp0s1: Gained carrier
déc. 08 09:23:51 vm0 systemd-networkd[483]: enp0s1: DHCPv4 address 198.18.69.0/23, gateway 198.18.68.1 acquired from 198.18.68.1
déc. 08 09:23:51 vm0 systemd-networkd[483]: Could not set hostname: Access denied
déc. 08 09:23:52 vm0 systemd-networkd[483]: enp0s1: Gained IPv6LL
```
* Enfin, **systemd** fournit un outil de gestion en ligne de commande appelé `networkctl` qui permet, entre autres, de consulter l'état de la configuration réseau.
```bash
networkctl
```
```=
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier configured
2 enp0s1 ether routable configured
2 links listed.
```
```bash
networkctl status
```
```=
● State: routable
Online state: online
Address: 198.18.69.0 on enp0s1
2001:678:3fc:44:baad:caff:fefe:0 on enp0s1
fe80::baad:caff:fefe:0 on enp0s1
Gateway: 198.18.68.1 on enp0s1
fe80::9803:fff:fe68:ea4a on enp0s1
DNS: 172.16.0.2
déc. 08 09:10:25 vm0 systemd-networkd[454]: lo: Gained carrier
déc. 08 09:10:25 vm0 systemd-networkd[454]: Enumeration completed
déc. 08 09:10:25 vm0 systemd[1]: Started systemd-networkd.service - Network Configuration.
déc. 08 09:10:25 vm0 systemd-networkd[454]: lo: Configuring with /etc/systemd/network/01-lo-default.network.
déc. 08 09:10:25 vm0 systemd-networkd[454]: enp0s1: Configuring with /etc/systemd/network/10-vm-default.network.
déc. 08 09:10:25 vm0 systemd-networkd[454]: enp0s1: Link UP
déc. 08 09:10:25 vm0 systemd-networkd[454]: enp0s1: Gained carrier
déc. 08 09:10:25 vm0 systemd-networkd[454]: enp0s1: DHCPv4 address 198.18.69.0/23, gateway 198.18.68.1 acquired from 198.18.68.1
déc. 08 09:10:26 vm0 systemd-networkd[454]: Could not set hostname: Access denied
déc. 08 09:10:27 vm0 systemd-networkd[454]: enp0s1: Gained IPv6LL
```
## La résolution des noms de domaine
Maintenant que l'on sait que les paquets IPv4 et IPv6 sont routables depuis l'interface réseau, il faut s'occuper de la correspondance entre les noms de domaine et les adresses IP.
Là encore, **systemd** fournit un service appelé `systemd-resolved` qui sert à définir les adresses IPv4 et/ou IPv6 des hôtes qui prennent en charge les requêtes du service DNS en fonction des différentes propositions faites par les outils de configuration automatique tels que DHCP pour IPv4 ou SLAAC pour IPv6.
### Q8	 Quel est l'état du service `systemd-resolved` ?
Si on reprend la même démarche que pour l'interface réseau, on échoue ...
```bash
systemctl status systemd-resolved
```
```=
Unit systemd-resolved.service could not be found.
```
En fait, ce service est fourni par un paquet qui n'est pas installé sur notre système. On procède donc à son installation pour avancer dans la configuration.
```bash
sudo apt install systemd-resolved
```
On nous recommande de redémarrer le système pour que la combinaison des deux services `systemd-networkd` et `systemd-resolved` produise une configuration cohérente.
On en arrive à l'objet de la question : l'état du service.
```bash
systemctl status systemd-resolved.service
```
```=
● systemd-resolved.service - Network Name Resolution
Loaded: loaded (/lib/systemd/system/systemd-resolved.service; enabled; preset: enabled)
Active: active (running) since Fri 2023-12-08 09:44:04 CET; 2min 58s ago
Docs: man:systemd-resolved.service(8)
man:org.freedesktop.resolve1(5)
https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
Main PID: 438 (systemd-resolve)
Status: "Processing requests..."
Tasks: 1 (limit: 1079)
Memory: 7.6M
CPU: 143ms
CGroup: /system.slice/systemd-resolved.service
└─438 /lib/systemd/systemd-resolved
déc. 08 09:44:04 vm0 systemd[1]: Starting systemd-resolved.service - Network Name Resolution...
déc. 08 09:44:04 vm0 systemd-resolved[438]: Positive Trust Anchors:
déc. 08 09:44:04 vm0 systemd-resolved[438]: . IN DS 20326 8 2 e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d
déc. 08 09:44:04 vm0 systemd-resolved[438]: Negative trust anchors: home.arpa 10.in-addr.arpa 16.172.in-addr.arpa 17.172.in-addr.arpa 18.172.in-addr.arpa 19.172.in-addr.arpa 20.172.in-addr.arpa 21.172.in-addr.arpa 22.172.in-addr.arpa 23.172.in-addr.ar>
déc. 08 09:44:04 vm0 systemd-resolved[438]: Using system hostname 'vm0'.
déc. 08 09:44:04 vm0 systemd[1]: Started systemd-resolved.service - Network Name Resolution.
déc. 08 09:44:38 vm0 systemd-resolved[438]: Clock change detected. Flushing caches.
```
La ligne 3 montre que le service est actif et en cours d'exécution.
Tout comme avec la configuration de l'interface réseau, on dispose d'un outil spécifique de gestion de la résolution des noms de domaines : `resolvectl`.
```bash
resolvectl
```
```=
Global
Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (enp0s1)
Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 mDNS/IPv4 mDNS/IPv6
Protocols: +DefaultRoute +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 172.16.0.2
DNS Servers: 172.16.0.2 2001:678:3fc:3::2
```
### Q9	 Comment tester la résolution DNS ?
On utilise la commande `host` suivi d'un nom d'hôte pour afficher les résultats.
```bash
host quad9.net
```
```=
quad9.net has address 216.21.3.77
quad9.net has IPv6 address 2620:0:871:9000::77
quad9.net mail is handled by 5 mx1.quad9.net.
quad9.net mail is handled by 20 mx2.quad9.net.
quad9.net mail is handled by 10 mx4.quad9.net.
```
On obtient bien les adresses IPv4 et IPv6 correspondant au nom [quad9.net](https://quad9.net) ainsi que la liste des serveurs de courrier électronique du domaine.
On peut compléter cette étape par l'affichage de l'adresse du *resolver* utilisé.
```bash
host -v quad9.net
```
```=
Trying "quad9.net"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53056
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;quad9.net. IN A
;; ANSWER SECTION:
quad9.net. 919 IN A 216.21.3.77
Received 43 bytes from 127.0.0.53#53 in 0 ms
Trying "quad9.net"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37244
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;quad9.net. IN AAAA
;; ANSWER SECTION:
quad9.net. 275 IN AAAA 2620:0:871:9000::77
Received 55 bytes from 127.0.0.53#53 in 0 ms
Trying "quad9.net"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54324
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;quad9.net. IN MX
;; ANSWER SECTION:
quad9.net. 19 IN MX 20 mx2.quad9.net.
quad9.net. 19 IN MX 5 mx1.quad9.net.
quad9.net. 19 IN MX 10 mx4.quad9.net.
Received 87 bytes from 127.0.0.53#53 in 0 ms
```
Les résultats de cette dernière commande montrent que l'adresse utilisée pour relayer les requêtes DNS est : `127.0.0.53`.
Cette adresse est définie dans le fichier *historique* de désignation des adresses IP de *resolvers* DNS.
```bash
grep -Ev '(^$|^#)' /etc/resolv.conf
```
```=
nameserver 127.0.0.53
options edns0 trust-ad
search .
```
## La synchronisation horaire
On reprend la même démarche avec la synchronisation de l'horloge du système avec le protocole réseau NTP (*Network Time Protocol*).
Le gestionnaire d'initialisation **systemd** fournit à nouveau un service dédié appelé : `systemd-timesyncd`.
### Q10	 Quel est l'état du service `systemd-timesyncd` ?
On fait encore appel à la commande `systemctl`.
```bash
systemctl status systemd-timesyncd
```
```=
● systemd-timesyncd.service - Network Time Synchronization
Loaded: loaded (/lib/systemd/system/systemd-timesyncd.service; enabled; preset: enabled)
Active: active (running) since Fri 2023-12-08 09:44:04 CET; 27min ago
Docs: man:systemd-timesyncd.service(8)
Main PID: 450 (systemd-timesyn)
Status: "Contacted time server [2001:41d0:701:1100::6e05]:123 (2.debian.pool.ntp.org)."
Tasks: 2 (limit: 1079)
Memory: 1.8M
CPU: 76ms
CGroup: /system.slice/systemd-timesyncd.service
└─450 /lib/systemd/systemd-timesyncd
déc. 08 09:44:04 vm0 systemd[1]: Starting systemd-timesyncd.service - Network Time Synchronization...
déc. 08 09:44:04 vm0 systemd[1]: Started systemd-timesyncd.service - Network Time Synchronization.
déc. 08 09:44:05 vm0 systemd-timesyncd[450]: Network configuration changed, trying to establish connection.
déc. 08 09:44:07 vm0 systemd-timesyncd[450]: Network configuration changed, trying to establish connection.
déc. 08 09:44:08 vm0 systemd-timesyncd[450]: Network configuration changed, trying to establish connection.
déc. 08 09:44:38 vm0 systemd-timesyncd[450]: Contacted time server [2001:41d0:701:1100::6e05]:123 (2.debian.pool.ntp.org).
déc. 08 09:44:38 vm0 systemd-timesyncd[450]: Initial clock synchronization to Fri 2023-12-08 09:44:38.262532 CET.
```
On constate avec l'information donnée en ligne 3 que le service est actif.
Les lignes suivantes donnent l'adresse IPv6 du serveur NTP de référence utilisé pour synchroniser l'horloge de la machine virtuelle.
### Q11	 Comment visualiser l'heure au niveau système ?
Tout comme pour la configuration des interfaces réseau et la résolution des noms, on dispose d'une commande ad hoc : `timedatectl`.
```bash
timedatectl
```
```=
Local time: ven. 2023-12-08 10:29:39 CET
Universal time: ven. 2023-12-08 09:29:39 UTC
RTC time: ven. 2023-12-08 09:29:39
Time zone: Europe/Paris (CET, +0100)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
```
La ligne 6 montre que le protocole NTP est utilisé pour définir l'heure du système.
## Conclusion
Une fois que l'on a vérifié que les trois services sont actifs et que l'on a pu tester leur fonctionnement, on dispose d'un système correctement configuré avec le gestionnaire d'initialisation **systemd**.
Comme toujours, l'histoire ne s'arrête pas là !
Il va falloir s'occuper de l'automatisation et de la programmation des configuration réseau dans les prochains épisodes.