Title: Introduction to nftables on Linux
       Author: Solène
       Date: 06 February 2023
       Tags: linux firewall nftables
       Description: In this article, I'll share my simple setup using nftables
       
       # Introduction
       
       Linux kernel has an integrated firewall named netfilter, but you
       manipulate it through command lines such as the good old iptables, or
       nftables which will eventually superseed iptables.
       
       Today, I'll share my experience in using nftables to manage my Linux
       home router, and my workstation.
       
       I won't explain much in this blog post because I just want to introduce
       nftables and show what it looks like, and how to get started.
       
       I added comments in my configuration files, I hope it's enough to get a
       grasp and make you curious to learn about nftables if you use Linux.
       
       # Configurations
       
       nftables works by creating a file running `nft -f` in the shebang, this
       allows atomic replacement of the ruleset if it's valid.
       
       Depending on your system, you may need to run the script at boot, but
       for instance on Gentoo, a systemd service is provided to save rules
       upon shutdown and restore them at boot.
       
       ## Router
       
       ```nftables
       #!/sbin/nft -f
       flush ruleset
       
       table inet filter {
       
           # defines a list of networks for further reference
           set safe_local {
               type ipv4_addr
               flags interval
       
               elements = { 10.42.42.0/24 }
           }
       
           chain input {
               # drop by default
               type filter hook input priority 0; policy drop;
               ct state invalid drop comment "early drop of invalid packets"
       
               # allow connections to work when initiated from this system
               ct state {established, related} accept comment "accept all connections related to connections made by us"
       
               # allow loopback
               iif lo accept comment "accept loopback"
       
               # remove weird packets
               iif != lo ip daddr 127.0.0.1/8 drop comment "drop connections to loopback not coming from loopback"
               iif != lo ip6 daddr ::1/128    drop comment "drop connections to loopback not coming from loopback"
       
               # make ICMP work
               ip protocol icmp accept comment "accept all ICMP types"
               ip6 nexthdr icmpv6 accept comment "accept all ICMP types"
       
               # only for known local networks
               ip saddr @safe_local tcp dport {22, 53, 80, 2222, 19999, 12344, 12345, 12346} accept
               ip saddr @safe_local udp dport {53} accept
       
               # allow on WAN
               iif eth0 tcp dport {80} accept
               iif eth0 udp dport {7495} accept
           }
       
           # allow NAT to get outside
           chain lan_masquerade {
               type nat hook postrouting priority srcnat;
               meta nfproto ipv4 oifname "eth0" masquerade
           }
       
           # port forwarding
           chain lan_nat {
               type nat hook prerouting priority dstnat;
               iif eth0 tcp dport 80 dnat ip to 10.42.42.102:8080
           }
       
       }
       ```
       
       ## Workstation
       
       ```nftables
       #!/sbin/nft -f
       
       flush ruleset
       
       table inet filter {
       
           set safe_local {
               type ipv4_addr
               flags interval
       
               elements = { 10.42.42.0/24, 10.43.43.1/32 }
           }
       
           chain input {
               # drop by default
               type filter hook input priority 0; policy drop;
               ct state invalid drop comment "early drop of invalid packets"
       
               # allow connections to work when initiated from this system
               ct state {established, related} accept comment "accept all connections related to connections made by us"
       
               # allow loopback
               iif lo accept comment "accept loopback"
       
               # remove weird packets
               iif != lo ip daddr 127.0.0.1/8 drop comment "drop connections to loopback not coming from loopback"
               iif != lo ip6 daddr ::1/128    drop comment "drop connections to loopback not coming from loopback"
       
               # make ICMP work
               ip protocol icmp accept comment "accept all ICMP types"
               ip6 nexthdr icmpv6 accept comment "accept all ICMP types"
       
               # only for known local networks
               ip saddr @safe_local tcp dport 22 accept comment "accept SSH"
               ip saddr @safe_local tcp dport {7905, 7906} accept comment "accept musikcube"
               ip saddr @safe_local tcp dport 8080 accept comment "accept nginx"
               ip saddr @safe_local tcp dport 1714-1764 accept comment "accept kdeconnect TCP"
               ip saddr @safe_local udp dport 1714-1764 accept comment "accept kdeconnect UDP"
               ip saddr @safe_local tcp dport 22000 accept comment "accept syncthing"
               ip saddr @safe_local udp dport 22000 accept comment "accept syncthing"
               ip saddr @safe_local tcp dport {139, 775, 445} accept comment "accept samba"
               ip saddr @safe_local tcp dport {111, 775, 2049} accept comment "accept NFS TCP"
               ip saddr @safe_local udp dport 111 accept comment "accept NFS UDP"
       
               # for my public IP over VPN
               ip daddr 78.224.46.36 udp dport 57500-57600 accept comment "accept mosh"
               ip6 daddr 2a00:5854:2151::1 udp dport 57500-57600 accept comment "accept mosh"
       
           }
       
           # drop anything that looks forwarded
           chain forward {
               type filter hook forward priority 0; policy drop;
           }
       
       }
       ```
       
       # Some commands
       
       If you need to operate a firewall using nftables, you may use `nft` to
       add/remove rules on the go instead of using the script with the
       ruleset.
       
       However, let me share a small cheatsheet of useful commands:
       
       ## List rules
       
       If you need to display the current rules in use:
       
       ```shell
       nft list ruleset
       ```
       
       ## Flush rules
       
       If you want to delete all the rules, just use:
       
       ```shell
       nft flush ruleset
       ```
       
       # Going further
       
       If you want to learn more about nftables, there is the excellent man
       page of the command `nft`.
       
       I used some resources from Arch Linux and Gentoo that you may also
       enjoy:
       
 (HTM) Gentoo Wiki: Nftables
 (HTM) Gentoo Wiki: Nftables examples
 (HTM) Arch Linux Wiki: Nftables