table inet fwl { # ── let rfc1918 ────────────────────────────────────────────────────────── set rfc1918 { type ipv4_addr flags interval elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } } # ── let open_ports : Set ─────────────────────────────────────────── set open_ports { type inet_service elements = { 22 } } # ── let forwards_v6 : Set<(Protocol, IP, Port)> ────────────────────────── set forwards_v6 { type inet_proto . ipv6_addr . inet_service elements = { tcp . 2001:db8::1 . 22000 } } # ── let forwards : Map<(Protocol, Port), (IP, Port)> ──────────────────── map forwards { type inet_proto . inet_service : ipv4_addr . inet_service elements = { tcp . 8080 : 10.0.0.10 . 80 } } # ── zone lan_zone = { lan } ────────────────────────────────────────────── # Zones compile to anonymous sets wherever referenced in iifname/oifname. # With a single member the set degenerates to a plain string match, # but we keep the set form so the compiler output is uniform regardless # of zone size. set lan_zone { type ifname elements = { "lan" } } # ── policy input ───────────────────────────────────────────────────────── chain input { type filter hook input priority filter; policy drop; ct state { established, related } accept iifname "lo" accept meta nfproto ipv6 ip6 nexthdr ipv6-icmp ip6 saddr fe80::/10 accept meta nfproto ipv4 meta l4proto tcp tcp dport @open_ports accept meta nfproto ipv4 meta l4proto udp udp dport 51944 accept } # ── policy forward ─────────────────────────────────────────────────────── chain forward { type filter hook forward priority filter; policy drop; ct state { established, related } accept ct status dnat accept # | Frame(iif in lan_zone -> wan, _) -> Allow meta iifname @lan_zone meta oifname "wan" accept # | Frame(wan -> iif in lan_zone, IPv4 TCP|UDP) if (proto,dport) in forwards meta iifname "wan" meta oifname @lan_zone \ meta nfproto ipv4 meta l4proto { tcp, udp } \ meta l4proto . th dport @forwards accept # | Frame(wan -> iif in lan_zone, IPv6 TCP|UDP) if (proto,dst,dport) in forwards_v6 meta iifname "wan" meta oifname @lan_zone \ meta nfproto ipv6 meta l4proto { tcp, udp } \ meta l4proto . ip6 daddr . th dport @forwards_v6 accept } # ── policy output ──────────────────────────────────────────────────────── chain output { type filter hook output priority filter; policy accept; } # ── policy nat_prerouting ──────────────────────────────────────────────── chain nat_prerouting { type nat hook prerouting priority dstnat; policy accept; meta nfproto ipv4 meta l4proto { tcp, udp } \ fib daddr type local \ dnat ip to meta l4proto . th dport map @forwards } # ── policy nat_postrouting ─────────────────────────────────────────────── chain nat_postrouting { type nat hook postrouting priority srcnat; policy accept; meta oifname "wan" meta nfproto ipv4 ip saddr @rfc1918 masquerade } }