logo rss

Comment configurer le pare-feu nftables sous Linux avec des exemples

Netfilter logo

nftables est le nouvel outil pour gérer le firewall du noyau Linux : Netfilter, il est amené à remplacer iptables. Je poste ici des exemples de configuration sur lesquels je m'appuie.

Configuration

  • OS : Debian 12
  • nftables : 1.0.6

Informations générales

  • Activer le service nftables au démarrage avec la commande systemctl:
root@host:~# systemctl enable nftables.service
  • Fichier de configuration nftables:
root@host:~# /etc/nftables.conf
  • Charger le fichier nftables:
root@host:~# nft -f /etc/nftables.conf
  • Afficher les règles courantes:
root@host:~# nft list ruleset
  • Effacer les règles:
root@host:~# nft flush ruleset
  • Notes :
    • inet inclus les adresses ipv4 et ipv6. On peut utiliser les mots ip pour les adresses ipv4 ou ipv6 pour les adresses ipv6.
    • iif pour input interface et oif pour output interface.
    • La règle log prefix "NFTABLES LOG : " permet de tracer le trafic la traversant dans /var/log/syslog.

SMTP Server

Un fichier de configuration pour un serveur smtp.

#!/usr/sbin/nft -f

flush ruleset

# ----- IPv4 -----
table ip filter {
        chain INPUT {
                type filter hook input priority 0; policy drop; #by default, we drop traffic

                iif lo accept comment "Accept any localhost traffic"
                ct state invalid counter drop comment "Drop invalid connections"
                ct state { established, related } counter accept comment "Accept traffic originated from us"
                iif != lo ip daddr 127.0.0.1/8 counter drop comment "drop connections to loopback not coming from loopback"

                ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept comment "Accept ICMP"
		
		iif eth0 ip saddr 10.0.0.10 tcp dport ssh ct state { new, related, established } counter accept comment "Accept ssh from 10.0.0.10"
                tcp dport { smtp, 465, 143, 993 } ct state { new, related, established } counter accept comment "Accept imap, imaps, smtp protocols"
		log prefix "INPUT : " #trace dropped traffic (use journalctl -k --grep="INPUT")
                counter drop #count and drop
        }
        chain FORWARD {
                type filter hook forward priority 0; policy drop;
                counter comment "count dropped packets"
        }
        chain OUTPUT {
                type filter hook output priority 0; policy accept;
        }
}

# ----- IPv6 -----
table ip6 filter {
        chain INPUT {
                type filter hook input priority 0; policy drop; #by default, we drop traffic

                iif lo accept comment "Accept any localhost traffic"
                iif != lo ip6 daddr ::1/128 counter drop comment "drop connections to loopback not coming from loopback"
                ct state invalid drop comment "Drop invalid connections"
                ct state { established, related } accept comment "Accept traffic originated from us"

                ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept comment "Accept ICMPv6"
                #ip protocol igmp accept comment "Accept IGMP"

                tcp dport { smtp, 465, 143, 993 } ct state { new, related, established } counter accept comment "Accept imap, imaps, smtp"
                counter drop #count and drop
        }
        chain FORWARD {
                type filter hook forward priority 0; policy drop;
                counter comment "count dropped packets"
        }
        chain OUTPUT {
                type filter hook output priority 0;
        }
}

Routeur

Un fichier de configuration pour un routeur.

#!/usr/sbin/nft -f

flush ruleset

table ip my_nat {
        chain my_masquerade {
                type nat hook postrouting priority 100; policy accept;
                ip daddr != { 192.168.0.0/16 } oifname "wan" masquerade comment "outgoing NAT"
        }

        chain my_prerouting {
                type nat hook prerouting priority -100; policy accept;
                iifname "wan" tcp dport { http, https } dnat to 192.168.10.250 comment "Web Redirect"
                iifname "wan" udp dport 9994 dnat to 192.168.10.251:1194 comment "OpenVPN Redirect"
        }
}
table inet filter {
        chain input {
                type filter hook input priority 0; policy drop;
                iif "lo" accept
                ct state { related, established} accept
                ct state invalid drop
                meta l4proto icmp accept
                ip saddr 192.168.0.0/16 tcp dport { ntp, domain, ssh } ct state { new, related, established } accept comment "dns, ntp, ssh"
                ip saddr 192.168.0.0/16 udp dport { ntp, domain } ct state { new, related, established } accept comment "dns, ntp"
                iifname "wan" jump input_wan
                iifname "lan" jump input_lan
		log prefix "INPUT : " #trace dropped traffic (use journalctl --grep=INPUT")
        }

        chain input_wan {
                ip saddr { 46.105.57.169 } tcp dport ssh accept comment "allow external SSH"
        }

        chain input_lan {
                tcp dport ssh accept
        }

        chain forward {
                type filter hook forward priority 0; policy drop; #by default, we drop traffic 
                ct state { related, established } accept
                ct state invalid drop
                ip saddr 192.168.0.0/16 tcp dport { http, https } accept comment "accept WEB"
                iifname { "lan" } oifname "wan" udp dport { domain, ntp } accept comment "DNS"
                ip saddr 192.168.0.0/16 ip daddr 192.168.0.0/16 icmp type { echo-reply, echo-request} accept comment "allow icmp"
        }

        chain output {
                type filter hook output priority 0; policy accept;
        }
}