#!/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é. # Séparer ipv4 et ipv6 simplifie le travail... table inet firewall { # ------------------------------ # Define : des trucs à déclarer une fois ici # ------------------------------ # Le nom de nos interfaces 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 } } # Blocklist : ce qui est bloqué durablement. Alimenté par Reaction/Fail2ban. # Interval : permet de bloquer des plages d'ip. set blocklist_v4 { type ipv4_addr flags interval } set blocklist_v6 { type ipv6_addr 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 } 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 } } # ------------------------------ # Autorisations explicites # TODO : Adapter au réel ;) # ------------------------------ chain confperso { # Autoriser SSH si : # - source = Bastion1 (externe). mettre son ip, c'est pas 101.1.1.1 # - OU source dans le LAN 192.168.1.0/24 (UNIQUEMENT quand on est derrière une box) # SSH ne sera sans doute pas sur le port 22, adapter... ip saddr @allowlistsys tcp dport 22 ct state new accept # Autoriser certains ports quand les services liés sont actifs, ici le web tcp dport { 80, 443 } ct state new accept # Proxmox : autoriser l’accès à l’interface web uniquement depuis certaines ip (fixes, perso) ip saddr @allowlistsys tcp dport 8006 accept tcp dport 8006 drop # Refuser tout le reste } # ------------------------------ # 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 durablement ip saddr @blocklist_v4 drop ip6 saddr @blocklist_v6 drop # Ou dans la liste temporaire ip saddr @tempblock_v4 drop ip6 saddr @tempblock_v6 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 # 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) # Ping normal : 1/s. Attention des outils de monitorings peuvent être plus rapides (jusque 20/s). # Ping IPv4 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 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 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 # Mais on ne rejette pas tout, faut bien que les serveurs puissent se saluer # Les attaques sur syn sont plus fréquentes, valeur entre 50 et 100, rst répond donc idem, # 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 # Autoriser ARP (sinon les VMs se retrouvent isolées) meta iifname $IFACES_LAN ether type arp accept # 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.255, 224.0.0.1 } iifname != $IFACES_LAN drop # Protection contre le SMTP/Email Bombing 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 (peuvent servir de honeypot) # 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 @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK BADPORT]" 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 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 add @tempblock_v4 { ip saddr } counter log prefix "[TEMPBLOCK SCAN]" 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,related accept # Autorise le loopback sortant oifname "lo" accept # Autorise le ping sortant ip protocol icmp accept ip6 nexthdr icmpv6 accept # Autoriser d'aller sur internet et de contacter les dns (domain) tcp dport { http, https } 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 } # ------------------------------ # 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 } }