#!/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 { # Liste pour bannir les IP malveillantes temporairement set blocklist { type addr # Ceci va ajuster le temps de bannissement suivant les récidives flags timeout } # Et ceci est le compteur pour les récidivistes set offender_count { type addr counters } # Set dynamique pour suivre les (plages) IP suspectes en temps réel set realtime_block { type addr family inet hash size 1024 timeout 10s # Timeout après 10 secondes } # ------------------------------ # Règles spécifiques IPv6 # ------------------------------ chain input_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 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 # Protège contre certaines attaques de spoofing en s'assurant que ces messages viennent bien d’un hôte local. ip6 saddr fe80::/10 icmpv6 type { 130, 131, 132, 143, 151, 152, 153 } accept # Vérifie si l'IP est bannie # On différencie ipv4 et ipv6 parce que si les règles sont les mêmes (cf plus bas), # visiblement ça va aider de filtrer par type d'ip ip6 saddr @blocklist drop # Mise à jour du compteur de récidive IPv6 # 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 udp, syn, 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 # ------------------------------ 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; # Vérifie si l'IP est bannie ip saddr @blocklist drop # Mise à jour du compteur de récidive IPv4 ip saddr @offender_count update counter ip saddr @offender_count counter > 5 add @blocklist { ip saddr timeout 1h } ip saddr @offender_count counter > 3 add @blocklist { ip saddr timeout 30m } 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 ct state vmap { established : accept, related : accept, invalid : drop } # Autorise le loopback iifname "lo" accept ## Mesures anti-DDoS # 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). icmp type echo-request limit rate 10/second accept icmp type echo-request limit rate over 10/second add @offender_count { ip saddr } drop # Protection contre UDP Flood ip protocol udp limit rate over 200/second add @offender_count { ip saddr } drop # Protection contre le DNS Query Flood ip protocol udp th dport 53 limit rate over 50/second add @offender_count { ip saddr } drop # Protection contre le SYN Flood, ACK Flood & RST Flood tcp flags syn limit rate over 100/second add @offender_count { ip saddr } drop tcp flags ack limit rate over 100/second add @offender_count { ip saddr } drop tcp flags rst limit rate over 50/second add @offender_count { ip saddr } drop # Protection contre le Smurf Attack ip daddr 255.255.255.255 drop ip daddr 224.0.0.1 drop # Attention en cas d'utilisation d'un bridge, ça va mettre le boxon # Dans ce cas exclure spécifiquement d'après le nom du bridge #iifname != "br0" ip daddr 255.255.255.255 drop #iifname != "br0" ip daddr 224.0.0.1 drop # Protection contre le SMTP/Email Bombing ip protocol tcp th dport 25 limit rate over 10/second add @offender_count { ip saddr } drop # Protection contre les botnets sur les ports fréquemment ciblés # tcp : telnet (23, 2323), UPnP (7547) # 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 udp th dport { 11211, 1900, 389, 123, 48101 } add @offender_count { ip saddr } drop # 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 udp limit rate over 50/second counter add @offender_count { ip saddr } 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 "[nftables] Inbound Denied: " 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 # 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 } }