Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
pratique:informatique:parefeu:nftables [30/01/2025 20:17] – [Exemples de fichiers suivant les cas] Zatalyzpratique:informatique:parefeu:nftables [25/06/2025 20:40] (Version actuelle) – [Sur hyperviseur exposé sur internet] Zatalyz
Ligne 42: Ligne 42:
     * Les type peuvent être : ''filter'', ''route'', ''nat''.     * Les type peuvent être : ''filter'', ''route'', ''nat''.
     * Les hook peuvent être : ''prerouting'', ''input'', ''forward'', ''output'', ''postrouting''.     * Les hook peuvent être : ''prerouting'', ''input'', ''forward'', ''output'', ''postrouting''.
 +    * S'il n'y a pas la règle ''type [x] hook [y]'', la chaine ne sera pas interprétée, sauf à y faire appel dans une autre chaine (cf détail de syntaxe plus bas). 
   * ''priority filter'' : quand tu ne sais pas, tu met filter, mais y'a d'autres options. ''filter'' ça précise les règles qui vont suivrent et qui ici sont donc de filtrer... Sinon il y a des chiffres (voir la doc) pour préciser dans quel ordre tout va s'appliquer.    * ''priority filter'' : quand tu ne sais pas, tu met filter, mais y'a d'autres options. ''filter'' ça précise les règles qui vont suivrent et qui ici sont donc de filtrer... Sinon il y a des chiffres (voir la doc) pour préciser dans quel ordre tout va s'appliquer. 
   * Peu importe l'ordre des ''chain'' et des ''table''. Par contre il faut déclarer le type de filtre dans les chaines, même si d'autres type de règles sont possibles.    * Peu importe l'ordre des ''chain'' et des ''table''. Par contre il faut déclarer le type de filtre dans les chaines, même si d'autres type de règles sont possibles. 
Ligne 48: Ligne 49:
  
 Quelque soit la version, je préfère une politique où je refuse tout, en dehors de ce qui est explicitement autorisé.  Quelque soit la version, je préfère une politique où je refuse tout, en dehors de ce qui est explicitement autorisé. 
 +
  
 ==== Options ==== ==== Options ====
Ligne 82: Ligne 84:
     * ''153'' MLD Multicast Router Termination : Un routeur annonce qu’il ne relaie plus le multicast     * ''153'' MLD Multicast Router Termination : Un routeur annonce qu’il ne relaie plus le multicast
  
-== Smurf Attack == +=== Smurf Attack === 
-C'est une attaque assez sournoise. En français "Attaque par rebond" mais c'est moins drôle comme nom.+C'est une attaque assez sournoise. En français "Attaque par rebond" mais c'est moins drôle comme nom. C’est une attaque par amplification où un attaquant envoie des paquets ICMP Echo Request (ping) avec une IP source usurpée (celle de la victime) à une adresse de diffusion (broadcast), souvent 255.255.255.255 (broadcast limité) ou 224.0.0.1 (multicast “all hosts”). Tous les hôtes qui reçoivent ça répondent à l’IP usurpée, il y a saturation du réseau et DoS ciblé.
  
 Il y a deux cas de figures. Il y a deux cas de figures.
Ligne 92: Ligne 94:
 ip daddr 224.0.0.1 drop</code> ip daddr 224.0.0.1 drop</code>
  
-Mais si on utilise un bridge réseau (cas classique quand on a un hyperviseur), on risque de mettre un sacré boxon dans le réseau interne, et il faut être plus fin. La solution basique consiste à utiliser le nom du réseau et donc à utiliser la règle suivante (si le bridge est br0) :  +Mais si on utilise un bridge réseau (cas classique quand on a un hyperviseur), on risque de mettre un sacré boxon dans le réseau interne, et il faut être plus fin.
-<code># Protection contre le Smurf Attack +
-iifname != "br0" ip daddr 255.255.255.255 drop +
-iifname != "br0" ip daddr 224.0.0.1 drop</code> +
-Ou même autoriser explicitement ARP (adresses MAC) et DHCP :  +
-<code># Protection contre le Smurf Attack +
-# Laisser passer ARP (sinon les VM ne pourront pas résoudre les adresses IP en MAC) +
-arp accept+
  
-# Laisser passer DHCP (car les requêtes DHCP utilisent 255.255.255.255) +La solution basique consiste à utiliser le nom du réseau (via un ''define IFACES_LAN = { "lo", "xenbr0" }''((Si le bridge est ''xenbr0'')) en début de table en général) et à utiliser la règle suivante : on bloque tout broadcast qui ne vient pas des interfaces internes, mais on autorise explicitement ARP((Adresses MAC)) et DHCP((les requêtes DHCP des VM utilisent 255.255.255.255)) à fonctionner en interne sinon on va être coincé.
-ip protocol udp th dport 67 accept +
-ip protocol udp th dport 68 accept+
  
-Bloquer les broadcasts/multicasts seulement sur les interfaces externes +<code bash>Autoriser ARP (sinon les VMs se retrouvent isolées) 
-iifname != "br0" ip daddr 255.255.255.255 drop +meta iifname $IFACES_LAN ether type arp accept 
-iifname != "br0" ip daddr 224.0.0.1 drop</code>+# Autoriser DHCP (indispensable avec des VMs clients DHCP) 
 +meta iifname $IFACES_LAN ip protocol udp udp dport { 67, 68 } accept 
 +# Bloquer le broadcast limité uniquement sur le WAN 
 +ip daddr 255.255.255.255224.0.0.1 } iifname != $IFACES_LAN drop</code>
  
 <WRAP center round info 100%> <WRAP center round info 100%>
-L'adaptation des règles dépend très fortement du type de pont. Je sens que ça va me filer des boutons. N'utilisez cette règle qu'en vérifiant son effet.+L'adaptation des règles dépend très fortement du type de pont. N'utilisez cette règle qu'en vérifiant son effet
 + 
 +Pour ipv6, ça a encore l'air d'être une autre affaire. Je ne maitrise pas.
 </WRAP> </WRAP>
  
-==== Autres éléments de syntaxe ====+=== Différence entre saddr et daddr === 
 +  * saddr : "Source address" soit l'ip source, permet de filtrer en fonction de l'expéditeur. 
 +  * daddr : "Destination address" soit l'ip de destination, permet de filtrer en fonction du destinataire. 
 + 
 +=== Autres éléments de syntaxe ===
 <WRAP center round info 60%> <WRAP center round info 60%>
 Je copie des "hook" pour comprendre ce que chaque petit morceau fait. Je copie des "hook" pour comprendre ce que chaque petit morceau fait.
Ligne 147: Ligne 149:
 }</code> }</code>
  
-On peut aussi définir des variables avec ''define'' (au début du fichier plutôt) et ensuite les appeler. +On peut aussi définir des variables avec ''define'' (au début du fichier plutôt, mais dans la table) et ensuite les appeler. 
-<code>define tcp_ports = {80, 443}+<code>
 table inet firewall { table inet firewall {
-        chain inbound { +  define tcp_ports = {80, 443} 
-                type filter hook input priority 0; policy drop; +  chain inbound { 
-                tcp dport { $tcp_ports } ct state new accept+    type filter hook input priority 0; policy drop; 
 +    tcp dport { $tcp_ports } ct state new accept 
 +  } 
 +}
  
 </code> </code>
  
 +=== Modulariser : une ou plusieurs chaines/fichiers ? ===
 +Comme expliqué en intro, on peut donner n'importe quel nom à une chaine, mais il y a des conditions pour qu'elle soit exécutée. 
  
-==== Exemples de fichiers suivant les cas ==== +  * Une chaine est exécutée si elle a l'élément ''type [x] hook [y]'' 
-=== Machine seule === +  * Ou si elle a été appelé depuis une autre chaine avec ''jump machaine''.
-Pour un dédié, une machine exposé directement à internet, voici la configuration de base. On va adapter un peu dans les chapitres suivants pour les fonctionnements avec hyperviseurs et machines derrière des proxy+
  
-C'est abondament commenté pour s'y retrouver...+Par exemple :  
 +<code> 
 +table inet firewall { 
 +  chain inbound { 
 +    type filter hook input priority 0; policy drop; 
 +      jump machinssh 
 +  } 
 +  chain machinssh { 
 +    counter comment "Compteur SSH" 
 +  } 
 +
 +</code> 
 + 
 +Pourquoi faire "jump" et pas simplement tout mettre dans la même chaine ?  
 +  * Quand une règle doit être appelée plusieurs fois (par exemple pour input ET output) 
 +  * pour déclarer 
 +  * Pour clarifier les blocs et potentiellement n'intervenir que sur un bout. Cela pourrait être des fichiers séparés, modifiés par Ansible par exemple.  
 +  * Il suffit de commenter un "jump" pour désactiver tout ce qui ne va pas avec ;) 
 + 
 +Exemple d'architecture avec des fichiers séparés :  
 +<code>/etc/nftables.d/ 
 +├── 00-definitions.nft 
 +├── 10-sets.nft 
 +├── 20-input.nft 
 +├── 30-fight.nft 
 +├── 40-confperso.nft 
 +└── 99-main.nft</code> 
 + 
 +Le nftables.conf ressemblera alors à ceci :  
 +<code bash nftables.conf>#!/usr/sbin/nft -f 
 + 
 +flush ruleset 
 + 
 +include "/etc/nftables.d/00-definitions.nft" 
 +include "/etc/nftables.d/10-sets.nft" 
 +include "/etc/nftables.d/20-input.nft" 
 +include "/etc/nftables.d/30-fight.nft" 
 +include "/etc/nftables.d/40-confperso.nft"</code> 
 + 
 +Cela permet alors de ne recharger/modifier qu'un seul des fichiers. Ils peuvent même être générés dynamiquement (par des scripts, Fail2ban ou Reaction).  
 + 
 +=== Ips martiennes === 
 +Quand j'ai lu dans une doc de pare-feu "pensez aussi aux plages privées et martiennes", j'ai cru à une blague. Mais on dirait que non. Ce sont des adresses réservées à certains usages et qui viennent d'interfaces précises ou alors... c'est du spoofing. Donc, dans les règles nftables, on vérifie si l'usage de ces ip arrivent du bon endroit et sinon on interdit.  
 + 
 +^ Plage IPv4           ^ Description                               ^ 
 +| '0.0.0.0/8'          | Adresses "This network" (source invalide) | 
 +| '10.0.0.0/8'         | Adresse privées réseau interne (RFC1918) 
 +| '100.64.0.0/10'      | Carrier-grade NAT (RFC6598), non publique | 
 +| '127.0.0.0/8'        | Loopback (localhost)                      | 
 +| '169.254.0.0/16'     | Link-local (APIPA)                        | 
 +| '172.16.0.0/12'      | Adresse privées réseau interne (RFC1918) 
 +| '192.0.0.0/24'       | IETF Protocol Assignments                 | 
 +| '192.0.2.0/24'       | TEST-NET-1 (documentation et test)        | 
 +| '192.88.99.0/24'     | 6to4 Relay Anycast                        | 
 +| '192.168.0.0/16'     | Adresse privées réseau interne (RFC1918) 
 +| '198.18.0.0/15'      | Benchmarking (RFC2544)                    | 
 +| '198.51.100.0/24'    | TEST-NET-2 (documentation et test)        | 
 +| '203.0.113.0/24'     | TEST-NET-3 (documentation et test)        | 
 +| '224.0.0.0/4'        | Multicast                                 | 
 +| '240.0.0.0/4'        | Adresses réservées pour futur usage       | 
 +| '255.255.255.255/32' | Broadcast limité                          | 
 + 
 +^ Plage IPv6      ^ Description                         ^ 
 +| '::1/128'       | Loopback                            | 
 +| '::/128'        | Adresse non spécifiée (unspecified) | 
 +| '::ffff:0:0/96' | IPv4-mapped IPv6 addresses          | 
 +| '64:ff9b::/96'  | IPv4/IPv6 translation (NAT64)       | 
 +| '100::/64'      | Discard prefix (RFC6666)            | 
 +| '2001::/23'     | IETF protocol assignments           | 
 +| '2001:db8::/32' | Documentation prefix                | 
 +| '2002::/16'     | 6to4 tunneling                      | 
 +| 'fc00::/7'      | Unique local addresses (ULA)        | 
 +| 'fe80::/10'     | Link-local addresses                | 
 +| 'ff00::/8'      | Multicast                           | 
 + 
 +Maintenant, on bloque quoi et quand ? Ça me donne mal au crâne, parce que bloquer le mauvais truc peut créer des bugs bizarres.  
 + 
 +On commence par "ip a" pour voir les interfaces actives sur notre serveur, qu'on déclarera avec "define" dans nftables.  
 + 
 +Un exemple sur un hyperviseur xen :  
 +  * ''lo'' (loopback) associé aux ip du type ''127.0.0.1'' / ''::1'' : cela ne doit concerner que le local. 
 +  * ''enp2s0'' : l'interface physique, mais aucune ip directe ne transitera par là dans notre cas, cela sera via le bridge. 
 +  * ''xenbr0'' : le bridge. Indique l'ip officielle de l'hyperviseur.  
 +  * ''vif1.0'', ''vif2.0'' : interface des VM, aucun impact en terme d'ip par rapport au nftables de l'hyperviseur. 
 + 
 + 
 + 
 +===== Exemples de fichiers suivant les cas ===== 
 +==== Sur hyperviseur exposé sur internet ==== 
 +C'est abondamment commenté donc ça devrait permettre de s'y retrouver.  
 + 
 +Il faut évidement relire, adapter les ip et les ports. 
 + 
 +J'ai mis une option : si l'hyperviseur est derrière une box, on peut permettre ssh en direct sur le réseau local (adresses en 192.168.1.*). Mais il ne faut pas permettre de le faire depuis les VM (10.0.0.*)... 
  
-<WRAP center round important 60%> +<WRAP center round important 100%> 
-Ce qui suit demande à être relu et adapté suivant le contexte ! +Ça <del>compile</delne génère pas d'erreur avec ''sudo nft -cof nftables.conf''. Ça ne veux pas dire que tout va marcher. J'ai pas encore assez testé certaines des règles. 
-</WRAP> +
-<WRAP center round todo 60%> +
-D'autant que je suis en train de bidouiller, j'ai pas encore tout "validé" et j'ai des restes de la version proxy, là :P+
 </WRAP> </WRAP>
  
Ligne 176: Ligne 272:
 flush ruleset flush ruleset
  
-# Table sur le trafic de type input/output/forward. De base on rejette tout, sauf ce qui est explicitement autorisé.+# Table sur le trafic de type input/output/forward.  
 +De base on rejette tout, sauf ce qui est explicitement autorisé. 
 +# Séparer ipv4 et ipv6 simplifie le travail... 
 table inet firewall { table inet firewall {
-    # Liste pour bannir les IP malveillantes temporairement +    # ------------------------------ 
-    set blocklist +    # Define : des trucs à déclarer une fois ici 
-        type addr +    # ------------------------------ 
-        # Ceci va ajuster le temps de bannissement suivant les récidives +    # Le nom de nos interfaces 
-        flags timeout+    define IFACES_LAN = { "lo", "xenbr0"
 +    define IFACES_WAN = { "enp2s0"
 +    # ------------------------------ 
 +    # SETS - alimenter des listes suivant des critères précis 
 +    # ------------------------------ 
 +    set allowlistsys 
 +        # Les ip autorisées à faire des trucs sur le réseau  
 +        # Ip internes et ip fixes de sysadmin 
 +        type ipv4_addr 
 +        flags interval 
 +        elements = { 109.190.202.194, 192.168.1.0/24 }
     }     }
-    # Et ceci est le compteur pour les récidivistes +    # Blocklist : ce qui est bloqué durablement. Alimenté par Reaction/Fail2ban. 
-    set offender_count +    # Interval : permet de bloquer des plages d'ip. 
-        type addr +    set blocklist_v4 
-        counters+        type ipv4_addr 
 +        flags interval
     }     }
-    # Set dynamique pour suivre les (plagesIP suspectes en temps réel +    set blocklist_v6 { 
-    set realtime_block +        type ipv6_addr 
-        type addr family inet hash+        flags interval 
 +    } 
 +    blocage temporaire à court terme en cas d'excès, timeout court (10s).  
 +    # Sert à "tamponner". Et à alimenter Blocklist au besoin. 
 +    set tempblock_v4 
 +        type ipv4_addr 
 +        flags timeout 
 +        timeout 10s
         size 1024         size 1024
-        timeout 10s  # Timeout après 10 secondes 
     }     }
 +    set tempblock_v6 { 
 +        type ipv6_addr 
 +        flags timeout 
 +        timeout 10s 
 +        size 1024 
 +    } 
 +    set martienne_v4 { 
 +        # Adresses non-routables ou réservées, si ça ne vient pas du bon port, c'est une attaque. 
 +        type ipv4_addr 
 +        flags interval 
 +        elements = { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.88.99.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4, 240.0.0.0/4 } 
 +    } 
 +    set martienne_v6 { 
 +        type ipv6_addr 
 +        flags interval 
 +        elements = { ::/128, ::1/128, ::ffff:0:0/96, 64:ff9b::/96, 100::/64, 2001::/23, 2001:db8::/32, 2002::/16, fc00::/7, fe80::/10, ff00::/8 } 
 +    }
     # ------------------------------     # ------------------------------
-    # Règles spécifiques IPv6+    # Autorisations explicites 
 +    # TODO : Adapter au réel ;)
     # ------------------------------     # ------------------------------
-    chain input_ipv6 +    chain confperso 
-        # Paquets ICMPv6 qui ne doivent pas être rejetés, voir https://tools.ietf.org/html/rfc4890#section-4.4.1 et https://wiki.nftables.org/wiki-nftables/index.php/Simple_ruleset_for_a_server +        # Autoriser SSH si : 
-        meta nfproto ipv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, echo-request, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, 148, 149 } accept +        # - source = Bastion1 (externe)mettre son ip, c'est pas 101.1.1.1 
-        # Protège contre certaines attaques de spoofing en s'assurant que ces messages viennent bien d’un hôte local. +        OU source dans le LAN 192.168.1.0/24 (UNIQUEMENT quand on est derrière une box
-        ip6 saddr fe80::/10 icmpv6 type { 130, 131, 132, 143, 151, 152, 153 } accept +        # SSH ne sera sans doute pas sur le port 22, adapter..
- +        ip saddr @allowlistsys tcp dport 22 ct state new accept 
-        # Vérifie si l'IP est bannie +        # Autoriser certains ports quand les services liés sont actifs, ici le web 
-        # On différencie ipv4 et ipv6 parce que si les règles sont les mêmes (cf plus bas),  +        tcp dport 80, 443 ct state new accept 
- # visiblement ça va aider de filtrer par type d'ip +        # Proxmox : autoriser l’accès à l’interface web uniquement depuis certaines ip (fixesperso
-        ip6 saddr @blocklist drop +        ip saddr @allowlistsys tcp dport 8006 accept 
-        # Mise à jour du compteur de récidive IPv6 +        tcp dport 8006 drop  # Refuser tout le reste
-        # Ces temps (10m, 30m, 1h) suffisent à limiter les attaques sans trop grossir la BL +
-        # et ne bloquent pas un humain de façon trop violente+
-        ip6 saddr @offender_count update counter +
-        ip6 saddr @offender_count counter > 5 add @blocklist { ip6 saddr timeout 1h } +
-        ip6 saddr @offender_count counter > 3 add @blocklist ip6 saddr timeout 30m } +
-        ip6 saddr @offender_count counter > 1 add @blocklist { ip6 saddr timeout 10m } +
- +
-        # Protection contre les attaques IPv6 (flood udpsyn, ack, rst, ping (on accepte+
-        ip6 nexthdr udp limit rate over 200/second add @offender_count { ip6 saddr } drop +
-        tcp flags syn limit rate over 100/second add @offender_count { ip6 saddr } drop +
-        tcp flags ack limit rate over 100/second add @offender_count { ip6 saddr } drop +
-        tcp flags rst limit rate over 50/second add @offender_count { ip6 saddr } drop +
-        icmpv6 type echo-request limit rate 10/second accept +
-        icmpv6 type echo-request limit rate over 10/second add @offender_count { ip6 saddr } drop+
     }     }
 +    
     # ------------------------------     # ------------------------------
     # Règles génériques entrantes     # Règles génériques entrantes
Ligne 233: Ligne 352:
         type filter hook input priority 0; policy drop;         type filter hook input priority 0; policy drop;
                  
-        # Vérifie si l'IP est bannie +        # Vérifie si l'IP est bannie durablement 
-        ip saddr @blocklist drop +        ip saddr @blocklist_v4 drop 
-        # Mise à jour du compteur de récidive IPv4 +        ip6 saddr @blocklist_v6 drop 
-        ip saddr @offender_count update counter +        # Ou dans la liste temporaire 
-        ip saddr @offender_count counter > 5 add @blocklist { ip saddr timeout 1h } +        ip saddr @tempblock_v4 drop 
-        ip saddr @offender_count counter > 3 add @blocklist { ip saddr timeout 30m } +        ip6 saddr @tempblock_v6 drop
-        ip saddr @offender_count counter > 1 add @blocklist { ip saddr timeout 10m }+
  
         # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides         # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides
         ct state vmap { established : accept, related : accept, invalid : drop }         ct state vmap { established : accept, related : accept, invalid : drop }
 +        
         # Autorise le loopback         # Autorise le loopback
         iifname "lo" accept         iifname "lo" accept
  
-        ## Mesures anti-DDoS+        # Spécial ipv6 
 +        # Paquets ICMPv6 qui ne doivent pas être rejetés, voir https://tools.ietf.org/html/rfc4890#section-4.4.1 et https://wiki.nftables.org/wiki-nftables/index.php/Simple_ruleset_for_a_server 
 +        ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, echo-request, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, 148, 149 } accept 
 +        # Protège contre certaines attaques de spoofing en s'assurant que ces messages viennent bien d’un hôte local. 
 +        meta iifname $IFACES_LAN ip6 saddr fe80::/10 icmpv6 type { 130, 131, 132, 143, 151, 152, 153 } accept 
 + 
 +        # Appelle les chaines utiles 
 +        jump confperso 
 +        jump fight 
 + 
 +    } 
 + 
 +    # ------------------------------ 
 +    # Mesures pour limiter diverses attaques 
 +    # ------------------------------ 
 +    chain fight { 
 +        # Empêcher le loopback reçu ailleurs que sur lo 
 +        ip saddr 127.0.0.0/8 iifname != "lo" drop 
 +        ip6 saddr ::1 iifname != "lo" drop 
 +        # Bloquer les IP martiennes si elles ne viennent pas de LAN 
 +        ip saddr @martienne_v4 iifname != $IFACES_LAN drop 
 +        ip6 saddr @martienne_v6 iifname != $IFACES_LAN drop 
 +        # Attention suivant le réseau local, il faut peut-être autoriser des ip explicitement (définir un set au besoin) 
 + 
         # Autorise le ping avec une limite pour les abus / Protection contre ICMP Flood (Ping Flood)         # Autorise le ping avec une limite pour les abus / Protection contre ICMP Flood (Ping Flood)
         # Ping normal : 1/s. Attention des outils de monitorings peuvent être plus rapides (jusque 20/s).         # Ping normal : 1/s. Attention des outils de monitorings peuvent être plus rapides (jusque 20/s).
-        icmp type echo-request limit rate 10/second accept +        # Ping IPv4 
-        icmp type echo-request limit rate over 10/second add @offender_count { ip saddr } drop+        ip protocol icmp icmp type echo-request limit rate 10/second accept 
 +        ip protocol icmp icmp type echo-request limit rate over 10/second add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK PING]" drop 
 +        # Ping IPv6 
 +        ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 10/second accept 
 +        ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 10/second add @tempblock_v6 { ip6 saddr } counter log prefix "[TEMPBLOCK PING6]" drop
  
         # Protection contre UDP Flood         # Protection contre UDP Flood
-        ip protocol udp limit rate over 200/second add @offender_count { ip saddr } drop +        ip protocol udp limit rate over 200/second add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK UDP]" drop 
 +        ip6 nexthdr udp limit rate over 200/second add @tempblock_v6 { ip6 saddr } counter log prefix "[TEMPBLOCK UDP6]" drop 
 +        
         # Protection contre le DNS Query Flood         # Protection contre le DNS Query Flood
-        ip protocol udp th dport 53 limit rate over 50/second add @offender_count { ip saddr } drop+        ip protocol udp th dport 53 limit rate over 50/second add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK DNS]" drop
  
         # Protection contre le SYN Flood, ACK Flood & RST Flood         # Protection contre le SYN Flood, ACK Flood & RST Flood
-        tcp flags syn limit rate over 100/second add @offender_count { ip saddr } drop +        # Mais on ne rejette pas tout, faut bien que les serveurs puissent se saluer 
-        tcp flags ack limit rate over 100/second add @offender_count { ip saddr } drop +        # Les attaques sur syn sont plus fréquentes, valeur entre 50 et 100, rst répond donc idem, 
-        tcp flags rst limit rate over 50/second add @offender_count { ip saddr } drop+        # mais ack bénéficie de valeurs plus hautes (jusque 200) 
 +        # Bref à adapter au trafic réel (=> monitoring !) 
 +        tcp flags syn,rst limit rate over 100/second add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK SYN]" drop 
 +        tcp flags ack limit rate over 100/second add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK ACK]" drop
  
 +        ip6 nexthdr tcp tcp flags syn,rst limit rate over 50/second add @tempblock_v6 { ip6 saddr } counter log prefix "[TEMPBLOCK SYN6]" drop
 +        ip6 nexthdr tcp tcp flags ack limit rate over 100/second add @tempblock_v6 { ip6 saddr } counter log prefix "[TEMPBLOCK ACK6]" drop
 +        
         # Protection contre le Smurf Attack         # Protection contre le Smurf Attack
-        ip daddr 255.255.255.255 drop +        # Autoriser ARP (sinon les VMs se retrouvent isolées) 
-        ip daddr 224.0.0.1 drop +        meta iifname $IFACES_LAN ether type arp accept 
-        # Attention en cas d'utilisation d'un bridgeça va mettre le boxon +        # Autoriser DHCP (indispensable avec des VMs clients DHCP) 
-        # Dans ce cas exclure spécifiquement d'après le nom du bridge +        meta iifname $IFACES_LAN ip protocol udp udp dport { 6768 } accept 
-        #iifname != "br0" ip daddr 255.255.255.255 drop +        # Bloquer le broadcast limité uniquement sur le WAN 
-        #iifname != "br0" ip daddr 224.0.0.1 drop+        ip daddr 255.255.255.255224.0.0.1 } iifname != $IFACES_LAN drop
  
         # Protection contre le SMTP/Email Bombing         # Protection contre le SMTP/Email Bombing
-        ip protocol tcp th dport 25 limit rate over 10/second add @offender_count { ip saddr } drop+        ip protocol tcp th dport 25 limit rate over 10/second add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK SMTP]" drop
  
-        # Protection contre les botnets sur les ports fréquemment ciblés+        # Protection contre les botnets sur les ports fréquemment ciblés (peuvent servir de honeypot)
         # tcp  : telnet (23, 2323), UPnP (7547)         # tcp  : telnet (23, 2323), UPnP (7547)
         # udp : Memcached (11211), SSDP (1900), LDAP (389), NTP (123), IoT (48101)          # udp : Memcached (11211), SSDP (1900), LDAP (389), NTP (123), IoT (48101) 
-        ip protocol tcp th dport { 23, 2323, 7547 } add @offender_count { ip saddr } drop +        ip protocol tcp th dport { 23, 2323, 7547 } add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK BADPORT]" drop 
-        ip protocol udp th dport { 11211, 1900, 389, 123, 48101 } add @offender_count { ip saddr } drop+        ip protocol udp th dport { 11211, 1900, 389, 123, 48101 } add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK BADPORT]" drop
  
         # Bloquer les scans de ports en cas de tentative de connexion rapide sur des ports multiples         # Bloquer les scans de ports en cas de tentative de connexion rapide sur des ports multiples
-        ip protocol tcp limit rate over 50/second counter add @offender_count { ip saddr } drop +        ip protocol tcp limit rate over 50/second add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK SCAN]" drop 
-        ip protocol udp limit rate over 50/second counter add @offender_count { ip saddr } drop +        ip protocol udp limit rate over 50/second add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK SCAN]" drop
-        # Règle de détection de scan de port via compteur (connexions multiples sur des ports distincts, ici 50 ports/seconde) +
-        ip protocol tcp sport != 0 limit rate over 50/second add @offender_count { ip saddr } drop +
- +
-        # Gestion des IP malveillantes (liste noire) +
-        ip saddr @blocklist drop +
- +
-        # Applique les règles en plus suivant le protocole (ici ipv6) +
-        meta protocol vmap { ip6 : jump input_ipv6 } +
- +
-        # Realtime Blocking pour détecter les attaques basées sur des plages d'IP +
-        ip saddr @realtime_block counter add @realtime_block { ip saddr } drop +
-        ip saddr @realtime_block limit rate over 200/second add @realtime_block { ip saddr } drop +
-         +
-        # Autoriser certains ports quand les services liés sont actifs (donc à adapter), ici le web et ssh +
-        tcp dport { 22, 80, 443 } ct state new accept +
- +
-        # Logging des connexions bloquées +
-        log prefix "[nftablesInbound Denied: counter drop+
     }     }
- 
     # ------------------------------     # ------------------------------
     # Règles génériques sortantes     # Règles génériques sortantes
     # ------------------------------     # ------------------------------
 +
     chain output {     chain output {
         # Par défaut, on rejette tout à moins de suivre une des règles ci-dessous.         # Par défaut, on rejette tout à moins de suivre une des règles ci-dessous.
         type filter hook output priority 0; policy drop;         type filter hook output priority 0; policy drop;
         # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides         # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides
-        ct state established accept+        ct state established,related accept
         # Autorise le loopback sortant         # Autorise le loopback sortant
         oifname "lo" accept         oifname "lo" accept
         # Autorise le ping sortant         # Autorise le ping sortant
         ip protocol icmp accept         ip protocol icmp accept
 +        ip6 nexthdr icmpv6 accept
         # Autoriser d'aller sur internet et de contacter les dns (domain)         # Autoriser d'aller sur internet et de contacter les dns (domain)
         tcp dport { http, https } accept         tcp dport { http, https } accept
         udp dport domain accept         udp dport domain accept
 +        tcp dport domain accept
 +        # Autoriser msmtp à envoyer ses mails
 +        tcp dport { 25, 465, 587 } ct state new,established accept
 +        # Autoriser NTP
 + udp dport { 53, 123 } ct state new,established accept
 +        # Log de ce qui est bloqué
 +        log prefix "[NFT OUTPUT DROP] " flags all drop
 +       
     }     }
  
Ligne 328: Ligne 473:
         # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides         # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides
         ct state established accept         ct state established accept
-        # Redirection des connexions web vers la VM 69 (si c'est le proxy). TODO différence daddr/saddr 
-        ip daddr 10.10.10.69 tcp dport { http, https } accept 
-        ip saddr 10.10.10.69 udp dport domain accept 
-        ip saddr 10.10.10.69 tcp dport { http, https } accept 
     }     }
 } }
  
-# Table sur le trafic de type prerouting/postrouting, par défaut sur accept pour que les connexions puissent s'initialiser 
-table ip nat { 
-    chain prerout { 
-        type nat hook prerouting priority 0; policy accept; 
-        # ce qui va sur les ports web doit être redirigé vers la VM 
-        tcp dport { http, https } dnat to 10.10.10.69 
-    } 
- 
-    chain postrout { 
-        type nat hook postrouting priority 0; policy accept; 
-        # Ce qui vient de la VM et qui tente de se connecter au web doit sortir par l'ip de notre proxy 
-        # Sinon on est redirigé sur nous-même... 
-        ip saddr 10.10.10.69 snat to 66.66.66.66 
-    } 
-} 
  
 </code> </code>
  
-=== Machine terminale === +=== Ports suivant les services ===
-<WRAP center round todo 60%> +
-À reprendre +
-</WRAP> +
- +
-Config dans une vm après un proxy etc. Cette machine est placée derrière un routeur (box, proxy...) qui sera un peu plus complet, et surtout qui empêche déjà de rentrer n'importe comment. +
-<code bash /etc/nftables.conf> +
-#!/usr/sbin/nft -f +
- +
-flush ruleset +
- +
-table inet firewall { +
-        # Règles spécifiques ipv6 +
-        chain inbound_ipv6 { +
-            # accept neighbour discovery otherwise connectivity breaks +
-            # source : https://wiki.nftables.org/wiki-nftables/index.php/Simple_ruleset_for_a_server +
-            icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept +
-            # TODO comprendre ! ICMPv6 packets which must not be dropped, see https://tools.ietf.org/html/rfc4890#section-4.4.1 +
-            meta nfproto ipv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, echo-request, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, 148, 149 } accept +
-            ip6 saddr fe80::/10 icmpv6 type { 130, 131, 132, 143, 151, 152, 153 } accept +
-        } +
-  +
-        # Règles génériques entrantes +
-        chain inbound { +
-            # Par défaut, on rejette tout à moins de suivre une des règles ci-dessous. +
-            type filter hook input priority 0; policy drop; +
-            # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides +
-            ct state vmap { established : accept, related : accept, invalid : drop } +
-            # Autorise le loopback +
-            iifname "lo" accept +
-            # Autorise le ping avec une limite pour les abus +
-            icmp type echo-request limit rate 5/second accept +
-            # Applique les règles en plus suivant le protocole(ici ipv6, on pourrait ajouter des trucs sur ipv4) +
-            meta protocol vmap { ip6 : jump inbound_ipv6 } +
-            # Autoriser certains ports quand les services liés sont actifs (donc à adapter), ici le web et ssh +
-            tcp dport { 22, 80, 443 } ct state new accept +
-            # Uncomment to enable logging of denied inbound traffic +
-            # log prefix "[nftables] Inbound Denied: " counter drop +
-            # TODO ! count and drop any other traffic +
-            #counter drop +
-        } +
-        # En sortie (output) par défaut ça autorise tout et en théorie c'est ok. +
-        # forward, nat etc : pas utile dans ce cas de figure. +
-+
- +
-</code>+
  
 Si serveur mail : remplacer Si serveur mail : remplacer
Ligne 408: Ligne 489:
   tcp dport { 22, 80, 443, 25, 587, 993, 4190 } ct state new accept   tcp dport { 22, 80, 443, 25, 587, 993, 4190 } ct state new accept
  
 +=== Todo ===
 +Faire plus modulaire. Adapter quand c'est pour une VM, un dédié... Mais la config de l'hyperviseur doit être une bonne base
  
-=== Machine proxy, configuration sécuritaire === 
-<WRAP center round todo 60%> 
-À reprendre ; mieux vaut utiliser ma première config ! 
-</WRAP> 
-Cette machine redirige une partie du trafic vers d'autres machines (probablement localement, mais ça peut être ailleurs) et on va donc ajouter NAT et Forward. Cas typique des proxy, xen, proxmox, etc.  
  
-Ici on va desservir l'ip interne (une VM) ''10.10.10.69'' (adresse à adapter suivant les machines derrière le proxy, donc). L'adresse ipv4 externe d'exemple est 66.66.66.66.  +===== Vérification et mise en place =====
- +
-<WRAP center round todo 60%> +
-Faudra améliorer sur ipv6. +
-</WRAP> +
- +
- +
-L'exemple est assez parano sur le trafic sortant et ce qui passe par l'autre machine, par défaut rien n'est permis sauf ce qui est explicite. On peut évidement être plus souple sur output/forward suivant les cas d'usage.  +
- +
-<code bash /etc/nftables.conf> +
-#!/usr/sbin/nft -f +
- +
-flush ruleset +
- +
-# Table sur le trafic de type input/output/forward. De base on rejette tout, sauf ce qui est explicitement autorisé. +
-table inet firewall { +
-        # Règles spécifiques ipv6 +
-        chain input_ipv6 { +
-            # accept neighbour discovery otherwise connectivity breaks +
-            # source : https://wiki.nftables.org/wiki-nftables/index.php/Simple_ruleset_for_a_server +
-            icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept +
-            # TODO comprendre ! ICMPv6 packets which must not be dropped, see https://tools.ietf.org/html/rfc4890#section-4.4.1 +
-            meta nfproto ipv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-reply, echo-request, nd-router-solicit,> +
-            ip6 saddr fe80::/10 icmpv6 type { 130, 131, 132, 143, 151, 152, 153 } accept +
-        } +
-  +
-        # Règles génériques entrantes (valables pour ipv6 et ipv4) +
-        chain input_all { +
-            # Par défaut, on rejette tout à moins de suivre une des règles ci-dessous. +
-            type filter hook input priority 0; policy drop; +
-            # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides +
-            ct state vmap { established : accept, related : accept, invalid : drop } +
-            # Autorise le loopback +
-            iifname "lo" accept +
-            # Autorise le ping avec une limite pour les abus +
-            icmp type echo-request limit rate 5/second accept +
-            # Applique les règles en plus suivant le protocole(ici ipv6, on pourrait ajouter des trucs sur ipv4) +
-            meta protocol vmap { ip6 : jump input_ipv6 } +
-            # Autoriser certains ports quand les services liés sont actifs (donc à adapter), ici le web et ssh +
-            tcp dport { 22, 80, 443 } ct state new accept +
-            # Uncomment to enable logging of denied inbound traffic +
-            # log prefix "[nftables] Inbound Denied: " counter drop +
-            # TODO ! count and drop any other traffic +
-            #counter drop +
-        } +
-        # Règles génériques sortantes +
-        chain output { +
-            # Par défaut, on rejette tout à moins de suivre une des règles ci-dessous. +
-            type filter hook output priority 0; policy drop; +
-            # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides +
-            ct state established accept +
-            # Autorise le loopback sortant +
-            oifname "lo" accept +
-            # Autorise le ping sortant +
-            ip protocol icmp accept +
-            # Autoriser d'aller sur internet et de contacter les dns (domain) +
-            tcp dport { http, https } accept +
-            udp dport domain accept +
-        } +
-        # Règles génériques "forward" (ce qui circule vers les autres adresses routées) +
-        chain forward { +
-            # Par défaut, on rejette tout à moins de suivre une des règles ci-dessous. +
-            type filter hook forward priority 0; policy drop; +
-            # Autoriser le trafic de paquets "etablished" et associés, supprimer les paquets non valides +
-            ct state established accept +
-            # transfère le web ? TODO différence daddr/saddr +
-            ip daddr 10.10.10.69 tcp dport { http, https } accept +
-            ip saddr 10.10.10.69 udp dport domain accept +
-            ip saddr 10.10.10.69 tcp dport { http, https } accept +
-    } +
-+
-# Table sur le trafic de type prerouting/postrouting, par défaut sur accept pour que les connexions puissent s'initialiser +
-table ip nat { +
-    chain prerout { +
-        type nat hook prerouting priority 0; policy accept; +
-        # ce qui va sur les ports web doit être redirigé vers la VM +
-        tcp dport { http, https } dnat to 10.10.10.69 +
-    } +
- +
-    chain postrout { +
-        type nat hook postrouting priority 0; policy accept; +
-        # Ce qui vient de la VM et qui tente de se connecter au web doit sortir par l'ip de notre proxy +
-        # Sinon on est redirigé sur nous-même... +
-        ip saddr 10.10.10.69 snat to 66.66.66.66 +
-    } +
-+
- +
-</code> +
- +
- +
-==== Vérification et mise en place ====+
  
 Pour vérifier ce fichier une fois modifié, avant de le mettre en place :  Pour vérifier ce fichier une fois modifié, avant de le mettre en place : 
Ligne 523: Ligne 511:
   sudo nft list ruleset   sudo nft list ruleset
  
-==== Sources ====+Pour recharger le fichier de configuration :  
 +  nft -f /etc/nftables.conf 
 + 
 +Admirer en temps réel les bans ? Pour admirer le contenu d'un set (par exemple tempblock_v4), c'est  
 +  sudo watch -n 1 'nft list set inet firewall tempblock_v4' 
 + 
 +Et pour les logs, si on a activé les [[pratique:informatique:systemd_error#avoir_des_vrais_journaux_de_log|logs lisibles]] (sinon, débrouillez vous avec journalctl) : 
 +  tail -f /var/log/kern.log  
 +===== Sources =====
  
   * https://wiki.nftables.org et en particulier   * https://wiki.nftables.org et en particulier
pratique/informatique/parefeu/nftables.1738264621.txt.gz · Dernière modification : 30/01/2025 20:17 de Zatalyz