DHCP


Journaux liées à cette note :

Mémento au sujet de QEMU et de sa configuration réseau #qemu, #network, #mémo, #ipv6, #mémento

Note de type #mémento #mémo au sujet des fonctionnalités network de QEMU.

Pour bien comprendre le fonctionnement de la configuration network de QEMU, il est important de bien saisir deux concepts :

  • les "virtual network device" (-device)
  • les "network backend" (-netdev)

There are two parts to networking within QEMU:

  • the virtual network device that is provided to the guest (e.g. a PCI network card).
  • the network backend that interacts with the emulated NIC (e.g. puts packets onto the host's network).

source

Voici toute la liste des network backend supportés par QEMU :

$ qemu-system-x86_64 -netdev help
Available netdev backend types:
socket
stream
dgram
hubport
tap
user
l2tpv3
bridge
af-xdp
vhost-user
vhost-vdpa

Dans cette note, je m'intéresse uniquement aux backend user, tap et bridge.


Le network backend user permet uniquement des accès sortant de la machine virtuelle vers Internet, mais pas l'inverse sans configurer un forwarding de port.
La configuration s'effectue via les options -netdev et -device :

$ qemu-system-x86_64 \
    ... \
    -netdev user,id=n1 \      # configuration du network backend
    -device e1000,netdev=n1 \ # virtual network device
    ...

La version 2.12 de QEMU (2018) propose une alternative plus simplifiée avec l'option -nic. Voici une exemple équivalent à la configuration ci-dessus :

$ qemu-system-x86_64 \
	... \
	-nic user,model=e1000

La version 2.12 de QEMU (2018) propose une alternative plus simplifiée avec l'option -nic. Voici un exemple équivalent à la configuration ci-dessus :

$ ip addr
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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
    altname enp0s3
    altname ens3
    altname enx525400123456
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic noprefixroute eth0
       valid_lft 47067sec preferred_lft 47067sec
    inet6 fec0::5054:ff:fe12:3456/64 scope site dynamic noprefixroute
       valid_lft 86251sec preferred_lft 14251sec
    inet6 fe80::5054:ff:fe12:3456/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

En approfondissant mes recherches, j'ai appris que quand le network backend user est configuré, QEMU prend en charge nativement les fonctionnalités DHCP et NAT. Il répond aux requêtes DHCP de la VM démarrée et gère aussi le routage IP en mode NAT.

On peut voir ici deux adresses IPv6 attachées à l'interface eth0 :

  • fec0::5054:ff:fe12:3456/64
  • fe80::5054:ff:fe12:3456/64

Une fois développées, ces deux adresses correspondent à :

  • fec0:0000:0000:0000:5054:00ff:fe12:3456
  • fe80:0000:0000:0000:5054:00ff:fe12:3456

Après avoir regardé cette vidéo, je pense avoir compris que dans une IPv6, la moitié gauche représente systématiquement un réseau (ici fe80:0000:0000:0000), nommé aussi "network prefix" ou "routing prefix", tandis que la partie de droite (ici 5054:00ff:fe12:3456) correspond à une adresse d'interface.

La partie interface de ces deux adresses est identique : 5054:00ff:fe12:3456.
Cette adresse d'interface est générée par conversion EUI-64 de l'adresse MAC 52:54:00:12:34:56 => 5054:00ff:fe12:3456.

Exemple de génération d'une autre adresse IPv6 si j'ajoute une interface réseau supplémentaire à la machine virtuelle :

3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:12:34:57 brd ff:ff:ff:ff:ff:ff
    altname enp0s4
    altname ens4
    altname enx525400123457
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic noprefixroute eth1
       valid_lft 86388sec preferred_lft 86388sec
    inet6 fec0::5054:ff:fe12:3457/64 scope site dynamic noprefixroute
       valid_lft 86389sec preferred_lft 14389sec
    inet6 fe80::5054:ff:fe12:3457/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

Ici on peut voir que la conversion EUI-64 de 52:54:00:12:34:57 donne 5054:ff:fe12:3457.

Par rapport au fonctionnement d'IPv4, je trouve que le mécanisme de génération automatique des adresses d'interface réseau d'IPv6 très bien conçu 👌.

Je m'intéresse maintenant aux préfixes d'adresses IPv6 fec0::/10 et fe80::/10.

Le préfixe fe80::/10 est réservé aux adresses Link-Local. Ces adresses sont automatiquement configurées sur toutes les interfaces IPv6 actives et permettent une communication uniquement au sein du même segment réseau.

Exemple, dans le schéma ci-dessous, tous les serveurs présents sur le réseau A sont joignables via l'adresse Link-Local.
Cependant, les serveurs A n'ont pas la possibilité d'atteindre les serveurs B via Link-Local.

Journal du dimanche 19 janvier 2025 à 11:24 #proxmox, #homelab, #network, #nftables, #iteration, #DevOps, #Server

#iteration Projet GH-271 - Installer Proxmox sur mon serveur NUC Intel i3-5010U, 8Go de Ram :

Être capable d'exposer sur Internet un port d'une VM.

source

Voici comment j'ai atteint cet objectif.

Pour faire ce test, j'ai installé un serveur http nginx sur une VM qui a l'IP 192.168.1.236.

Cette IP est attribuée par le DHCP installé sur mon routeur OpenWrt. Le serveur hôte Proxmox est configuré en mode bridge.

Ma Box Internet Bouygues sur 192.168.1.254 peut accéder directement à cette VM 192.168.1.236.

Pour exposer le serveur Proxmox sur Internet, j'ai configuré mon serveur Serveur NUC i3 gen 5 en tant que DMZ host.

J'ai suivi la recommandation pour éviter une attaque du type : DNS amplification attacks

DNS amplification attacks involves an attacker sending a DNS name lookup request to one or more public DNS servers, spoofing the source IP address of the targeted victim.

source

Avec cette configuration, je peux accéder en ssh au Serveur NUC i3 gen 5 depuis Internet.

J'ai tout de suite décidé d'augmenter la sécurité du serveur ssh :

# cat <<'EOF' > /etc/ssh/sshd_config.d/sklein.conf
Protocol 2
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
KbdInteractiveAuthentication no
X11Forwarding no
# systemctl restart ssh

J'ai ensuite configuré le firewall basé sur nftables pour mettre en place quelques règles de sécurité et mettre en place de redirection de port du serveur hôte Proxmox vers le port 80 de la VM 192.168.1.236.

nftables est installé par défaut sur Proxmox mais n'est pas activé. Je commence par activer nftables :

root@nuci3:~# systemctl enable nftables
root@nuci3:~# systemctl start nftables

Voici ma configuration /etc/nftables.conf, je me suis fortement inspiré des exemples présents dans ArchWiki : https://wiki.archlinux.org/title/Nftables#Server

# cat <<'EOF' > /etc/nftables.conf
flush ruleset;

table inet filter {
    # Configuration from https://wiki.archlinux.org/title/Nftables#Server
    set LANv4 {
        type ipv4_addr
        flags interval

        elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16 }
    }
    set LANv6 {
        type ipv6_addr
        flags interval

        elements = { fd00::/8, fe80::/10 }
    }

    chain input {
        type filter hook input priority filter; policy drop;
        iif lo accept comment "Accept any localhost traffic"

        ct state invalid drop comment "Drop invalid connections"
        ct state established,related accept comment "Accept traffic originated from us"

        meta l4proto ipv6-icmp accept comment "Accept ICMPv6"
        meta l4proto icmp accept comment "Accept ICMP"
        ip protocol igmp accept comment "Accept IGMP"

        udp dport mdns ip6 daddr ff02::fb accept comment "Accept mDNS"
        udp dport mdns ip daddr 224.0.0.251 accept comment "Accept mDNS"

        ip saddr @LANv4 accept comment "Connections from private IP address ranges"
        ip6 saddr @LANv6 accept comment "Connections from private IP address ranges"

        tcp dport ssh accept comment "Accept SSH on port 22"
        tcp dport 8006 accept comment "Accept Proxmox web console"

        udp sport bootpc udp dport bootps ip saddr 0.0.0.0 ip daddr 255.255.255.255 accept comment "Accept DHCPDISCOVER (for DHCP-Proxy)"
    }

    chain forward {
        type filter hook forward priority filter; policy accept;
    }

    chain output {
        type filter hook output priority filter; policy accept;
    }
}

table nat {
    chain prerouting {
        type nat hook prerouting priority dstnat;
        tcp dport 80 dnat to 192.168.1.236;
    }
    chain postrouting {
        type nat hook postrouting priority srcnat;
        masquerade
    }
}
EOF

Pour appliquer en toute sécurité cette configuration, j'ai suivi la méthode indiquée dans : "Appliquer une configuration nftables avec un rollback automatique de sécurité".

Après cela, voici les tests que j'ai effectués :

  • Depuis mon réseau local :
    • Test d'accès au serveur Proxmox via ssh : ssh root@192.168.1.43
    • Test d'accès au serveur Proxmox via la console web : https://192.168.1.43:8006
    • Test d'accès au service http dans la VM : curl -I http://192.168.1.236
  • Depuis Internet :
    • Test d'accès au serveur Proxmox via ssh : ssh root@176.142.86.141
    • Test que je n'ai pas accès au serveur Proxmox via la console web : curl http://176.142.86.141:8006
    • Test d'accès au service http dans la VM : curl -I http://176.142.86.141

Voilà, tout fonctionne correctement 🙂.

Prochaines étapes :

  • Être capable d'accéder depuis Internet via IPv6 à une VM
  • Je souhaite arrive à effectuer un déploiement d'une Virtual instance via Terraform

Journal du lundi 23 décembre 2024 à 19:39 #selfhosting, #proxmox, #DevOps, #bug, #iteration

J'ai commencé le Projet GH-271 - Installer Proxmox sur mon serveur NUC Intel i3-5010U, 8Go de Ram le 9 octobre.
Le 27 octobre, j'ai publié la note 2024-10-27_2109 qui contient une erreur qui m'a fait perdre 14h !

La ligne en question :

# virt-customize -a noble-server-cloudimg-amd64.img --install qemu-guest-agent --run-command 'systemctl enable qemu-guest-agent.service'
[   0.0] Examining the guest ...
[   4.5] Setting a random seed
virt-customize: warning: random seed could not be set for this type of
guest
[   4.5] Setting the machine ID in /etc/machine-id
[   4.5] Installing packages: qemu-guest-agent

[  32.1] Running: systemctl enable qemu-guest-agent.service
[  32.6] Finishing off

Je n'avais pas fait attention au message Setting the machine ID in /etc/machine-id 🙊.

Conséquence : le template Proxmox Ubuntu contenait un fichier /etc/machine-id avec un id.
Conséquence : toutes les Virtual machine que je créais sous Proxmox avaient la même valeur machine-id.

J'ai découvert que l'option 61 "Client identifier" du protocole DHCP permet de passer un client id au serveur DHCP qui sera utilisé à la place de l'adresse MAC.

Conséquence : le serveur DHCP assignait la même IP à ces Virtual machine.

J'ai pensé que le serveur DHCP de mon router BBox avait un problème. J'ai donc décidé d'installer Projet 15 - Installation et configuration de OpenWrt sur Xiaomi Mi Router 4A Gigabit pour avoir une meilleure maitrise du serveur DHCP.

Problème : j'ai fait face au même problème avec le serveur DHCP de OpenWrt.

Après quelques recherches, j'ai découvert que contrairement à virt-customize la commande virt-sysprep permet d'agir sur des images qui ont vocation à être clonées.

"Sysprep" stands for "system preparation" tool. The name comes from the Microsoft program sysprep.exe which is used to unconfigure Windows machines in preparation for cloning them.

source

Pour corriger le problème, j'ai remplacé cette ligne :

# virt-customize -a noble-server-cloudimg-amd64.img --install qemu-guest-agent --run-command 'systemctl enable qemu-guest-agent.service'

Par ces deux lignes :

# virt-sysprep -a noble-server-cloudimg-amd64.img --network --install qemu-guest-agent --run-command 'systemctl enable qemu-guest-agent.service'
# virt-sysprep --operation machine-id -a noble-server-cloudimg-amd64.img

La seconde commande permet de supprimer le fichier /etc/machine-id, ce qui corrige le problème d'attribution d'IP par le serveur DHCP.

À noter que je ne comprends pas pourquoi il est nécessaire de lancer explicitement cette seconde commande, étant donné que la commande virt-sysprep est destinée aux images de type "template". Le fichier /etc/machine-id ne devrait jamais être créé, ou tout du moins, automatiquement supprimé à la fin de chaque utilisation de virt-sysprep.

Maintenant, l'instanciation de Virtual machine fonctionne bien, elles ont des IP différentes 🙂.

Prochaine étape du Projet GH-271 :

Je souhaite arrive à effectuer un déploiement d'une Virtual instance via cli de Terraform.