Morpheus
Sécurité réseau / Lab local

Libvirt NAT & nftables

Exceptions nftables minimales pour conserver une politique forward deny-by-default tout en laissant fonctionner le NAT libvirt.

nftables libvirt NAT deny-by-default validation
Topologie publique host, VM et NAT
Topologie publique sans sous-réseaux ni interfaces réels: host, lab virtuel, flux locaux et frontières de filtrage.
01

Définir

Séparer host, loopback, VM NAT, services locaux et flux de maintenance.

02

Filtrer

Appliquer une politique entrante stricte avec exceptions motivées.

03

Tester

Valider syntaxe, connectivité locale, VM et absence d'ouverture inattendue.

04

Documenter

Conserver une procédure de diagnostic et de rollback.

Contexte

Le problème réel.

Une politique forward drop est saine pour un poste desktop sans routage, mais elle bloque les VM libvirt qui passent par le bridge NAT. Le défi est d'ouvrir seulement le transit nécessaire aux VM.

Objectifs

Ce que la solution devait garantir.

  • Réduire l'exposition réseau du poste.
  • Conserver la compatibilité avec libvirt NAT et les tests PRA.
  • Éviter les ouvertures implicites.
  • Différencier poste local et serveur exposé publiquement.
Architecture publique

Structure documentée, détails exploitables retirés.

Exemples anonymisés

Ce qui peut être montré sans exposer le système réel.

Table d'intentions réseau

Exemple basé sur la documentation nftables: politique entrante stricte, loopback autorisé, connexions établies conservées et libvirt isolé comme frontière dédiée.

flux                         décision
loopback                     autoriser
connexions établies          autoriser
nouvelle entrée poste        refus par défaut
diagnostic limité            autoriser avec limitation de débit
support NAT libvirt          autoriser seulement sur la frontière virtuelle
service admin inattendu      refuser et investiguer

Pseudo-ruleset expurgé

Cet extrait reprend la structure de la politique documentée sans interface, sous-réseau, port privé ni ruleset complet.

table inet filter
  chain input
    policy drop
    autoriser loopback
    drop trafic invalide
    autoriser established et related
    autoriser diagnostics limités
    refuser tout le reste

  chain forward
    policy drop
    autoriser seulement les flux documentés du lab virtuel

Validation après changement

La validation reprend le runbook: tester la syntaxe avant chargement, vérifier le service, puis confirmer que le lab virtuel fonctionne encore.

vérification syntaxe
contrôle statut service
contrôle connectivité locale
contrôle connectivité NAT libvirt
revue des ports ouverts inattendus
plan de rollback confirmé
Runbook public

Commandes et états attendus issus de la documentation privée.

Les commandes ci-dessous sont volontairement anonymisées: chemins, noms de machines, interfaces, dépôts, périphériques et actions destructrices sont remplacés par des placeholders.

Documentation privée: nftables

Validation nftables

Commandes anonymisées

nft -c -f <firewall-config>
systemctl status nftables.service --no-pager
nft list table inet filter
nft -s list ruleset

État attendu

la syntaxe est valide avant reload
le service nftables est actif
la chaîne input applique une policy drop
la chaîne forward applique une policy drop, sauf pour la frontière de lab documentée
la policy output reste acceptable pour un contexte desktop
Documentation privée: nftables

Tests de connectivité

Commandes anonymisées

ping -c 2 <public-resolver>
getent hosts <known-domain>
curl -I <known-https-url>
ping -c 2 127.0.0.1

État attendu

le trafic sortant fonctionne
la résolution DNS fonctionne
la réponse HTTPS est accessible
le loopback reste fonctionnel
l'hôte n'est toujours pas traité comme un serveur public
Documentation privée: libvirt-nat-nftables

Compatibilité libvirt

Commandes anonymisées

virsh -c qemu:///system net-info <nat-network>
virsh -c qemu:///system domiflist <test-vm>
nft list ruleset | rg 'policy|virtual-lab'
ip -4 a
ip route

État attendu

le réseau NAT libvirt est actif
la VM de test possède l'interface virtuelle attendue
DHCP et le NAT sortant fonctionnent dans la VM
forward drop reste la règle par défaut hors frontière virtuelle
aucune interface ou plage réelle n'est publiée
Travail réalisé

Décisions techniques publiables.

Deny-by-default

La politique refuse par défaut les entrées non attendues.

Libvirt

Les besoins de virtualisation sont explicités au lieu d'être noyés dans le ruleset.

Rollback

Le diagnostic réseau garde un chemin de retour pour éviter de bloquer le poste.

Validation

Preuves et contrôles retenus.

Preuves visuelles

Contrôles observables et portée de la preuve.

Résultats publics

Ce que le chantier démontre.

Anonymisation

Ce qui reste privé.

  • Pas de ruleset complet.
  • Pas de noms d'interfaces ni sous-réseaux réels.
  • Pas de ports privés spécifiques.
  • Pas de commande de désactivation firewall comme recette publique.
Sources privées

Documentation d'origine.

  • Documentation nftables.
  • Guide libvirt NAT avec nftables.
  • Hardening système.
  • Runbooks virtualisation et PRA.

Libvirt NAT avec nftables

Cette page complète le hardening nftables pour le cas où l'hôte lance des VM via libvirt NAT. Les noms d'interfaces réels, noms de VM et chemins de configuration sont remplacés par des placeholders lorsque nécessaire.

Problème

Une politique forward drop est correcte pour un desktop sans routage, mais elle bloque les VM libvirt qui passent par le bridge NAT.

Symptômes observables:

  • VM avec IPv6 mais pas d'IPv4 stable.
  • DHCP libvirt qui ne répond pas côté VM.
  • Réseau NAT default actif mais connectivité absente.
  • Restauration PRA impossible si l'ISO live doit installer des paquets depuis le réseau.

Vérifications

sudo virsh -c qemu:///system net-info default
sudo virsh -c qemu:///system domiflist <VM_PRA>
sudo nft list ruleset

Règles nftables nécessaires

Dans input, autoriser le DHCP libvirt reçu depuis le bridge libvirt:

chain input {
  type filter hook input priority filter;
  policy drop;

  iif lo accept
  ct state invalid drop
  ct state established,related accept
  meta l4proto { icmp, ipv6-icmp } limit rate 10/second accept
  udp sport 67 udp dport 68 accept

  iif "<LIBVIRT_BRIDGE>" udp sport 68 udp dport 67 accept
}

Dans forward, conserver policy drop, puis ajouter les exceptions libvirt:

chain forward {
  type filter hook forward priority filter;
  policy drop;

  iif "<LIBVIRT_BRIDGE>" accept
  oif "<LIBVIRT_BRIDGE>" ct state established,related accept
}

Ces règles autorisent le DHCP depuis les VM, le trafic sortant via NAT libvirt et les retours de connexions vers les VM.

Validation

Vérifier la syntaxe:

sudo nft -c -f <NFTABLES_CONFIG>

Recharger:

sudo systemctl restart nftables

Contrôler:

sudo nft list ruleset

Dans la VM:

ip -4 a
ip route

Note de sécurité

Ces règles ne transforment pas l'hôte en routeur général. Elles ouvrent seulement le transit nécessaire au bridge libvirt, tout en gardant le reste de forward en deny-by-default.