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 … | |
# 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 loopba… | |
iif != lo ip6 daddr ::1/128 drop comment "drop connections to loopba… | |
# 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, … | |
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 … | |
# 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 loopba… | |
iif != lo ip6 daddr ::1/128 drop comment "drop connections to loopba… | |
# 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 musi… | |
ip saddr @safe_local tcp dport 8080 accept comment "accept nginx" | |
ip saddr @safe_local tcp dport 1714-1764 accept comment "accept kdeconn… | |
ip saddr @safe_local udp dport 1714-1764 accept comment "accept kdeconn… | |
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 s… | |
ip saddr @safe_local tcp dport {111, 775, 2049} accept comment "accept … | |
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 "accep… | |
} | |
# 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: | |
Gentoo Wiki: Nftables | |
Gentoo Wiki: Nftables examples | |
Arch Linux Wiki: Nftables |