rss logo

nftables Linux firewall configuration files examples

Netfilter logo

nftables is going to replace iptables so to be in tune with the times, here, some notes to see how it works on a Debian system.

Configuration

  • OS : Debian 12
  • nftables : 1.0.6

General informations

  • Enable nftables service with systemctl so that it starts automatically at boot time:
root@host:~# systemctl enable nftables.service
  • Edit nftables rules file:
root@host:~# vim /etc/nftables.conf
  • Load nftables rules:
root@host:~# nft -f /etc/nftables.conf
  • Show current rules:
root@host:~# nft list ruleset
  • Clear the ruleset:
root@host:~# nft flush ruleset
  • Notes :
    • inet designates ipv4 and ipv6 addresses. ip word designates ipv4 addresses only and ipv6 word designates ipv6 addresses only.
    • iif means input interface and oif means output interface.
    • log prefix "NFTABLES LOG : " rule logs traffic passing through it in /var/log/syslog.

SMTP Server

A configuration file example that I use for a smtp server.

#!/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 --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; } }

Router

A configuration file that I use to configure routers.

#!/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 { auth, domain, ssh } ct state { new, related, established } accept comment "dns, ntp, ssh" ip saddr 192.168.0.0/16 udp dport { auth, 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; } }
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Contact :

contact mail address