Voici un audit approfondi du ruleset nftables que tu m’as envoyé, point par point avec une approche critique et rigoureuse.


🧨 1. Politiques DROP + chaînes vides = inefficaces ou incohérentes

default_fwd est vide :

                chain FORWARD {
    policy drop;
    jump global
    jump default_fwd
    ...
    reject
}

              
  • Effet : tout trafic de forward est bloqué par reject.

  • Attendu : des règles explicites pour permettre le passage de certains flux (ex: Docker vers Internet).

🔎 Même situation dans OUTPUT et INPUT : la logique dépend fortement de default_in et default_out.


🐳 2. Gestion Docker incomplète et parfois contradictoire

✅ Présence de chaînes Docker (DOCKER, DOCKER-FORWARD, etc.) :

Mais attention :

  • Ces chaînes sont dans une table séparée (ip filter), ce qui ne les rend pas visibles dans inet filter, qui a la main sur les hooks FORWARD, INPUT, etc.

  • Résultat : elles peuvent être déclarées, mais jamais appelées.

👎 Exemple :

                table ip filter {
  chain FORWARD {
    hook forward ...
  }
}

              

Mais table inet filter a aussi un hook forward. Seul un seul hook est actif par priorité ➤ le inet prend le dessus ici. Donc la table ip filter est non fonctionnelle (fantôme).


🌍 3. Sortie Internet des conteneurs Docker potentiellement bloquée

Même si la table ip nat a ceci :

                oifname != "br-8203e51da77b" ip saddr 172.18.0.0/16 masquerade

              

→ C’est bon en théorie, mais le FORWARD est en DROP, et la chaîne default_fwd est vide ⇒ aucune règle n’autorise la sortie.

Il manque :

                iifname "br-8203e51da77b" oifname != "br-8203e51da77b" accept

              

🌐 4. default_out = accept total, sans journalisation ni filtrage

                chain default_out {
    accept
}

              

→ Cela laisse passer tout, ce qui est OK si c’est voulu, mais :

  • Aucune granularité

  • Pas de log

  • Pas de contrôle par port

➡️ Un serveur de prod mérite mieux qu’un open bar anonyme.


🧱 5. Répétition de chaînes INPUT : conflit de priorité

Tu as deux chaînes INPUT :

  • Dans table inet filter (priority filter)

  • Dans table inet f2b-table (priority filter -1)

⚠️ Ça fonctionne, mais la logique est déroutante :

  • On ne voit pas facilement qui s’exécute avant quoi.

  • Cela fragilise le modèle mental du pare-feu.

➡️ Une seule chaîne INPUT, bien structurée, devrait suffire.


🔥 6. Pas de RETURN dans les jump

Partout dans les chaînes FORWARD, INPUT, etc. :

                jump global
jump default_fwd

              

sans return derrière, donc les règles suivantes continuent à s’exécuter, même si le jump match.

→ Risque : règles en double, rejets fantômes, logs imprévisibles.


🐞 7. Chaîne global présente mais peu utile sans return

                chain global {
    ip saddr @blackhole_v4 drop
    ip daddr @blackhole_v4 drop
    ...
}

              

Bien vu 👌, mais son effet est passif :

  • Pas de log

  • Pas de comment

  • Pas de différenciation INPUT/OUTPUT/FORWARD


8. Table ip6 nat presque vide, mais avec un jump DOCKER

                chain PREROUTING {
    fib daddr type local counter packets 0 bytes 0 jump DOCKER
}

              

Mais la chaîne DOCKER en ip6 nat est vide.

➡️ C’est inoffensif, mais ça alourdit le ruleset inutilement.


🧼 9. Redondance + complexité inutile = dette technique

Tu as :

  • table inet filter

  • table ip filter (pour Docker)

  • table inet f2b-table

  • table ip nat

  • table ip6 nat

  • table ip6 filter

  • table ip raw

Sans hiérarchie claire, ni commentaire, ni documentation. Résultat :

  • Impossible à maintenir pour un collègue

  • Effets de bord quasi garantis


✅ Recommandations concrètes

Objectif Action recommandée
🔥 Clarifier la structure Centraliser les règles dans table inet filter
🐳 Docker Ajouter iifname/oifname explicites en FORWARD
🔁 NAT Garder seulement table ip nat, supprimer ip6 nat si inutilisé
🔒 Fail2Ban Intégrer directement ses règles dans INPUT principale
🧹 Nettoyage Supprimer ip6 filter, raw, etc. sauf besoin réel
📜 Transparence Ajouter log, counter et comment partout
🧪 Débogage Ajouter log prefix AVANT tout reject