#!/usr/sbin/nft -f flush ruleset define wan = eth0 define vpn = wg0 define vpn_net = 10.0.0.0/24 define lan_net = 192.168.2.0/24 define self = 192.168.2.22 # delegated prefix is 2a02:a45e:ce93::/48 define lan_net6 = 2a02:a45e:ce93:0::/64 define icmpv4_basic = { echo-reply, # type 0 / ping echo-request, # type 8 / ping destination-unreachable, # type 3 time-exceeded, # type 11 parameter-problem, # type 12 } define icmpv6_basic = { # Basic echo-reply, # type 129 / ping echo-request, # type 128 / ping destination-unreachable, # type 1 packet-too-big, # type 2 time-exceeded, # type 3 parameter-problem # type 4 } define icmpv6_slaac = { # SLAAC nd-router-solicit, # type 133 nd-router-advert, # type 134 nd-neighbor-solicit, # type 135 nd-neighbor-advert # type 136 } # Clients that are allowed to access the LAN network define lan_clients = { 10.0.0.3 } table inet firewall { chain postrouting { type nat hook postrouting priority 100; # Masquerade WireGuard VPN WAN traffic to LAN subnet oifname $wan ip saddr $vpn_net masquerade } chain incoming { # This line set what traffic the chain will handle, the priority and default policy. # The priority comes in when you in another table have a chain set to "hook input" and want to specify in what order they should run. type filter hook input priority 0; policy drop; ct state invalid drop # early drop of invalid packets ct state { established, related } accept # allow established/related connections iif lo accept # allow traffic from loopback interface # Limit and accept ICMP packets ip protocol icmp icmp type $icmpv4_basic limit rate 1/second burst 5 packets accept ip6 nexthdr icmpv6 icmpv6 type $icmpv6_basic limit rate 1/second burst 5 packets accept icmpv6 type $icmpv6_slaac limit rate 1/second burst 5 packets ip6 hoplimit 255 accept # Rules for all interfaces tcp dport { 80, 443 } accept # Allow http and https for all interfaces udp dport 443 accept # Allow quic (http/3) for all interfaces ip saddr $lan_net tcp dport 22 accept # Allow SSH from LAN network # AdGuard admin access (8888) only from LAN and VPN ip saddr { $lan_net, $vpn_net } tcp dport 8888 accept ip6 saddr $lan_net6 tcp dport 8888 accept # Adguard DNS, DHCP, DoT, DoQ ports only from LAN and VPN ip saddr { $lan_net, $vpn_net} udp dport { 53, 67, 68, 784 } accept ip saddr { $lan_net, $vpn_net} tcp dport { 53, 853 } accept ip6 saddr $lan_net6 udp dport { 53, 67, 68, 784 } accept ip6 saddr $lan_net6 tcp dport { 53, 853 } accept # Rules for WAN interface only iifname $wan udp dport 51820 accept # Allow Wireguard incoming from WAN # iifname $wan tcp dport 22 limit rate 10/minute accept # Rate limit SSH (port 22) to 10 connections per minute from WAN # Rules for VPN interface only iifname $vpn tcp dport 22 accept # Allow SSH from VPN } chain forward { type filter hook forward priority 0; policy drop; ct state invalid drop # early drop of invalid packets ct state {established, related} accept # allow established/related connections iifname $vpn ip saddr $lan_clients ip daddr $lan_net accept # Allow specific clients to access the LAN network iifname $vpn ip daddr $lan_net drop # Block all other VPN clients from accessing the LAN network iifname $vpn oifname $wan accept # Allow VPN traffic to access WAN iifname "podman*" accept # allow traffic from podman interfaces (podman0, podman1, ...) oifname "podman*" accept # allow traffic to podman interfaces (podman0, podman1, ...) } chain outgoing { type filter hook output priority 0; policy accept; } }