Skip to content

Instantly share code, notes, and snippets.

@neingeist
Created February 8, 2022 18:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neingeist/c97b488f2511bb5ca07c8a07213eccbe to your computer and use it in GitHub Desktop.
Save neingeist/c97b488f2511bb5ca07c8a07213eccbe to your computer and use it in GitHub Desktop.
IPv4 nft ruleset with NAT hairpinning + using a portforward map (requires nftables >= 0.9.4)
#!/usr/sbin/nft -f
define out_if = "enp4s0"
define out_ip = 11.22.33.44/32
define vm_if = "br0"
define vm_net = 192.168.122.0/24
flush ruleset
table ip filter {
chain INPUT {
type filter hook input priority filter; policy drop;
iifname $out_if tcp dport 22 counter jump f2b-sshd
ct state related,established counter accept
iifname "lo" counter accept
meta l4proto icmp accept
tcp dport 22 counter accept
iifname $out_if udp sport 67-68 udp dport 67-68 counter accept
iifname $vm_if udp dport 53 counter accept
iifname $vm_if udp sport 67-68 udp dport 67-68 counter accept
counter reject with icmp type admin-prohibited
}
chain FORWARD {
type filter hook forward priority filter; policy drop;
ct state related,established counter accept
# portforwards are implicitly accepted
ct status dnat counter accept
iifname $vm_if ip saddr $vm_net counter accept
counter reject with icmp type admin-prohibited
}
chain OUTPUT {
type filter hook output priority filter; policy drop;
counter accept
}
chain f2b-sshd {
counter return
}
}
table ip nat {
map portforwards {
type inet_service : ipv4_addr . inet_service
elements = {
16085 : 192.168.122.2 . 22
}
}
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
# portforward (+ hairpinning)
iif {$out_if, $vm_if} ip protocol tcp ip daddr $out_ip dnat ip addr . port to tcp dport map @portforwards;
}
chain INPUT {
type nat hook input priority 100; policy accept;
}
chain OUTPUT {
type nat hook output priority -100; policy accept;
# portforwards for local connections
ip protocol tcp ip daddr $out_ip dnat ip addr . port to tcp dport map @portforwards;
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
# masquerade outgoing connections
iifname $vm_if oifname $out_if counter masquerade
# masquerade hairpinned connections
iifname $vm_if oifname $vm_if ct status dnat counter masquerade
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment