#!/usr/sbin/nft -f

flush ruleset

# --- CONFIGURATION VARIABLES ---
# WAN = Internet (Source of CAKE)
define WAN_IF = "enp1s0"
# LAN = Local Network (Source of DHCP)
define LAN_IF = "enp2s0"
define WG_IF = "wg0"
define DOCKER_NET = 172.18.0.0/16

table inet filter {
    flowtable f {
        hook ingress priority 0; devices = { enp1s0, enp2s0 };
    }

    chain input {
        type filter hook input priority 0; policy drop;

        # Accept loopback
        iifname "lo" accept

        # Accept established connections
        ct state established,related accept
        ct state invalid drop

        # Allow all from LAN and WireGuard interfaces to the router
        iifname { $LAN_IF, $WG_IF } accept

        # Allow WireGuard (Public WAN)
        udp dport 51820 accept

        # Allow ICMP (Ping) with rate limiting
        ip protocol icmp icmp type echo-request limit rate 5/second accept
        
        # Allow IPv6 ICMP (Neighbor Discovery is REQUIRED for IPv6 to work)
        icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert } accept

        # Allow DHCPv6 replies from ISP (UDP port 546)
        iifname $WAN_IF udp dport 546 accept

        # Allow HTTP/HTTPS for Caddy (Public for ACME/Web)
        tcp dport { 80, 443 } accept
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # Hardware Flow Offloading
        ip protocol { tcp, udp } flow offload @f

        # Drop invalid connections
        ct state invalid drop

        # Allow LAN to WAN
        iifname $LAN_IF oifname $WAN_IF accept

        # Allow WAN to LAN (only return traffic)
        iifname $WAN_IF oifname $LAN_IF ct state established,related accept
        
        # Allow LAN to WAN (IPv6)
        meta nfproto ipv6 iifname $LAN_IF oifname $WAN_IF accept
        # Allow WAN to LAN (IPv6 return traffic only)
        meta nfproto ipv6 iifname $WAN_IF oifname $LAN_IF ct state established,related accept

        # Allow WireGuard traffic
        iifname $WG_IF accept
        iifname $LAN_IF oifname $WG_IF accept
        oifname $WG_IF ct state established,related accept

        # Allow Docker traffic
        ip saddr $DOCKER_NET accept
        ip daddr $DOCKER_NET ct state established,related accept

        # --- CUSTOM FORWARD RULES ---
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

table ip nat {
    chain prerouting {
        type nat hook prerouting priority -100; policy accept;
        iifname { $LAN_IF, $WG_IF } meta l4proto { tcp, udp } th dport 53 redirect to :53

        # --- CUSTOM DNAT RULES ---
    }

    chain postrouting {
        type nat hook postrouting priority 100; policy accept;

        # Masquerade (NAT) traffic leaving WAN
        oifname $WAN_IF masquerade
    }
}
