#!/usr/sbin/nft -f # Performance West host firewall. # Goal: expose ONLY public-facing ports to the internet; keep all container / # k3s / loopback traffic fully open so nothing internal breaks. # # Dedicated table (pw_fw) with a high-priority (-150) input hook so it is # evaluated BEFORE kube-router's ACCEPT chain in the standard 'filter' table. # fail2ban (f2b-table) stays untouched. table inet pw_fw delete table inet pw_fw table inet pw_fw { set pub_tcp { type inet_service # Public-facing ports only. elements = { 22, 22022, 80, 443 } # NB: 22 kept too in case provider/console uses it; SSH is on 22022. } # Trusted admin source IPs allowed to reach git/forgejo (3022) and other # non-public admin ports. Update with: nft add element inet pw_fw trusted_admin { } # 207.174.124.51 = ezstorehost — clones site repos from forgejo during # static-tenant deploys (ezStorehost-infra provision-static-tenant.yml). set trusted_admin { type ipv4_addr flags interval elements = { 76.228.206.147, 24.162.76.14, 207.174.124.51 } } chain input { type filter hook input priority -150; policy accept; # 1) Always allow loopback + already-established flows. iif "lo" accept ct state established,related accept ct state invalid drop # 2) Fully trust internal networks (docker bridges, flannel pod/service, # cni0). Containers and k3s must keep talking unrestricted. ip saddr { 127.0.0.0/8, 172.16.0.0/12, 10.42.0.0/16, 10.43.0.0/16 } accept iifname { "docker0", "br-*", "cni0", "flannel.1", "kube-*", "veth*", "cilium*" } accept # 3) Allow ICMP (ping / path MTU) - safe and useful for diagnostics. ip protocol icmp accept ip6 nexthdr icmpv6 accept # 4) Trusted-admin allow-list for git/forgejo SSH (3022). ip saddr @trusted_admin tcp dport 3022 accept # 5) Public allow-list (new inbound from the internet). tcp dport @pub_tcp accept # 6) Everything else arriving on the public uplink is dropped. iifname "ens18" drop } }