nftables

nftables is the more modern replacement of iptables. Configuring it for ipv4 forwarding was suprisingly more difficult than expected. Now, with AI help it will certainly become easier but in the meantime, this page can be used as a working example.

In the code below, replace <WAN> with the interface name connected to internet and <LOCAL INTERFACE> with the interface connected to the local subnet.

/etc/nftables.conf:

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority filter;
    }
    chain forward {
        type filter hook forward priority filter;
    }
    chain output {
        type filter hook output priority filter;
    }
    chain forward {
        type filter hook forward priority 0; policy accept;
        iifname "<WAN>" oifname "<LOCAL INTERFACE>" ct state related,established  counter accept
        iifname "<LOCAL INTERFACE>" oifname "<WAN>" counter accept
    }
}

table inet nat {
    chain postrouting {
        type nat hook postrouting priority 100;
        oifname "<WAN>" counter masquerade
    }

}

Setup dnsmasq to serve the local network. Here the subnet is 192.168.1.x, the <WAN> dns is 192.168.0.254.

/etc/dnsmasq.d/<LOCAL INTERFACE>.cfg

# dnsmasq run on UDP port 53
port=53
listen-address=192.168.1.1
interface=<LOCAL INTERFACE>
bogus-priv
expand-hosts
domain=home
no-hosts

server=192.168.0.254

# enable DNS Cache and adjust cache-size
cache-size=1000

# enable DHCP via dnsmasq
# define lease db file
# make the dhcp server as an authoritative
dhcp-range=192.168.1.10,192.168.1.20,12h
dhcp-option=option:domain-name,home
dhcp-leasefile=/var/lib/misc/dnsmasq.leases
dhcp-authoritative

Do not forget to enable ip_forwarding by editing /etc/sysctl.conf` with net.ipv4.ip_forward=1` and to start nftable service: sudo systemctl enable nftables