kota's memex

general tips

You can name tables, chains etc whatever you like and you can have multiple sets of them. Specific settings on them control what they do and in what order they are run.

Whenever you have a need to specify a group of IP addresses, ports, interfaces and what not, use sets. They make rules non repetitive, easy to read and write and allow the system to optimise performance.

Rules with “limit” need to be put before rules accepting “established” connections.

If you do not have “policy accept” on your outgoing chain you need to explicitly allow IPv6 ICMP.

hook order

ingress -> prerouting -> input/output/forward -> postrouting

list full ruleset

nft list ruleset

DNAT

Destination NAT enables you to redirect traffic on a router to a host that is not directly accessible from the Internet.

List your ruleset and confirm you have a nat table and both pre and postrouting chains. Otherwise, create them with the following commands.

nft add table nat
nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
nft add chain nat postrouting { type nat hook postrouting priority 100 \; }

Even if you do not add a rule to the postrouting chain, the nftables framework requires this chain to match outgoing packet replies.

Add a rule to the prerouting chain that redirects incoming traffic on the enp1s0 interface sent to port 25565 to the host with the 192.168.2.2 IP:
nft add rule nat prerouting iifname enp1s0 tcp dport 25565 dnat to 192.168.2.2

Then add a masquerade rule to the postrouting table:
nft add rule ip nat postrouting oifname "enp1s0" snat to 45.32.78.230

Running these commands updates the "live" config, but if you want to have the config persist on reboot you need to setup a config file. This example config does DNAT for 25565 udp/tcp and 27960 udp:

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
	chain input {
		type filter hook input priority 0;
	}
	chain forward {
		type filter hook forward priority 0;
	}
	chain output {
		type filter hook output priority 0;
	}
}
table ip filter {
	chain FORWARD {
		type filter hook forward priority filter; policy accept;
		iifname "enp1s0" oifname "wg0" meta l4proto tcp tcp dport 25565 accept
		iifname "enp1s0" oifname "wg0" meta l4proto udp udp dport 25565 accept
		iifname "enp1s0" oifname "wg0" meta l4proto udp udp dport 27960 accept
		iifname "enp1s0" oifname "wg0" ct state related,established accept
		iifname "wg0" oifname "enp1s0" ct state related,established accept
	}
}
table ip nat {
	chain PREROUTING {
		type nat hook prerouting priority dstnat; policy accept;
		iifname "enp1s0" meta l4proto tcp tcp dport 25565 dnat to 192.168.2.2
		iifname "enp1s0" meta l4proto udp udp dport 25565 dnat to 192.168.2.2
		iifname "enp1s0" meta l4proto udp udp dport 27960 dnat to 192.168.2.2
	}

	chain POSTROUTING {
		type nat hook postrouting priority srcnat; policy accept;
		oifname "wg0" meta l4proto tcp ip daddr 192.168.2.2 tcp dport 25565 snat to 192.168.2.1
		oifname "wg0" meta l4proto udp ip daddr 192.168.2.2 udp dport 25565 snat to 192.168.2.1
		oifname "wg0" meta l4proto udp ip daddr 192.168.2.2 udp dport 27960 snat to 192.168.2.1
	}
}

tutorials

https://xdeb.org/post/2019/09/26/setting-up-a-server-firewall-with-nftables-that-support-wireguard-vpn/ https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/securing_networks/getting-started-with-nftables_securing-networks