#!/usr/sbin/nft -f # Géré par Ansible — ne pas modifier manuellement flush ruleset table inet filter { chain input { type filter hook input priority 0; policy drop; # Loopback iif lo accept # Connexions établies ct state established,related accept # ICMP ip protocol icmp accept ip6 nexthdr icmpv6 accept # SSH depuis le LAN domestique, le LAN cluster et le tunnel WireGuard tcp dport 22 ip saddr { 192.168.1.0/24, 192.168.10.0/24, 10.99.0.0/24 } accept # WireGuard — handshake/transport (Freebox 51820/udp → funk-s01) udp dport 51820 accept # DNS + DHCP (dnsmasq) — cluster + clients VPN (dnsmasq écoute aussi sur wg0) udp dport 53 ip saddr { 192.168.10.0/24, 10.99.0.0/24 } accept tcp dport 53 ip saddr { 192.168.10.0/24, 10.99.0.0/24 } accept udp dport 67 iif {{ lan_interface }} accept # NFS tcp dport { 111, 2049 } ip saddr 192.168.10.0/24 accept udp dport { 111, 2049 } ip saddr 192.168.10.0/24 accept # Services données (accès cluster uniquement) tcp dport { 5432, 6333, 6334, 9000, 9001 } ip saddr 192.168.10.0/24 accept # Monitoring — node_exporter (scraping par Prometheus : nœuds cluster + pods 10.42/16) tcp dport 9100 ip saddr { 192.168.10.0/24, 10.42.0.0/16 } accept # AlertManager webhook → Hermes monitor (pods k8s 10.42/16 + nœuds cluster) tcp dport 9093 ip saddr { 192.168.10.0/24, 10.42.0.0/16 } accept # Hermes gateway (accès LAN domestique + cluster + pods k8s pour alertmanager webhook) tcp dport 8080 ip saddr { 192.168.1.0/24, 192.168.10.0/24, 10.42.0.0/16 } accept # Hermes dashboard (poste admin uniquement) tcp dport 9119 ip saddr {{ hermes_dashboard_allowed_ip }} accept # LiteLLM proxy (pods k8s 10.42/16 + nœuds cluster + LAN domestique pour client vocal) tcp dport 4000 ip saddr { 192.168.1.0/24, 192.168.10.0/24, 10.42.0.0/16 } accept # Postfix relay SMTP (pods k8s 10.42/16 + nœuds cluster) tcp dport 25 ip saddr { 192.168.10.0/24, 10.42.0.0/16 } accept # Hermes auto-improve trigger server (pods k8s 10.42/16 + nœuds cluster) tcp dport 9095 ip saddr { 192.168.10.0/24, 10.42.0.0/16 } accept log prefix "nft-drop: " drop } chain forward { type filter hook forward priority 0; policy drop; # Forwarding LAN cluster → WAN (NAT sortant) iif {{ lan_interface }} oif {{ wan_interface }} ct state new,established,related accept # Forwarding LAN domestique → LAN cluster (accès admin depuis le poste perso) iif {{ wan_interface }} oif {{ lan_interface }} ip saddr 192.168.1.0/24 ct state new,established,related accept # Réponses WAN → cluster (connexions initiées depuis le cluster) iif {{ wan_interface }} oif {{ lan_interface }} ct state established,related accept # Satisfactory — trafic DNATé (192.168.1.200) → gpu-01, quelle que soit la source # (couvre un éventuel port-forward internet depuis la box). # 7777 = jeu/API ; 8888 = reliable messaging TCP (1.1) — bloqué = kick à ~60 s ip daddr 192.168.10.20 tcp dport { 7777, 8888 } ct state new,established,related accept ip daddr 192.168.10.20 udp dport 7777 ct state new,established,related accept # NOTE : les anciens chemins Internet :9081 (Authentik direct) / :9080 (Guacamole # direct), en HTTP clair vers les VIPs .201/.202, ont été FERMÉS au durcissement # (2026-07-07). Tout passe désormais par funklab.online en HTTPS (ci-dessous). # Les VIPs restent joignables en interne (LAN) ; seul l'accès Internet est retiré. # Penser à supprimer aussi les redirections Freebox 9080/9081 (elles pointent ici # dans le vide). Rétablir l'accès : re-DNAT ci-dessous + accept forward. # Domaine public funklab.online — Internet DNATé (80/443) → Traefik (.200). # Routage par sous-domaine + TLS Let's Encrypt côté Traefik. Rate-limit idem. ip daddr 192.168.10.200 tcp dport { 80, 443 } ct state new limit rate 60/minute burst 30 packets accept ip daddr 192.168.10.200 tcp dport { 80, 443 } ct state established,related accept # WireGuard → lab : filtrage par pair (host_vars wireguard_peers) {% for peer in wireguard_peers | selectattr('access', 'equalto', 'full') | list %} # {{ peer.name }} — accès complet iif "wg0" ip saddr {{ peer.ip }} ct state new,established,related accept {% endfor %} {% for peer in wireguard_peers | selectattr('access', 'equalto', 'portal') | list %} # {{ peer.name }} — portail Guacamole uniquement (Traefik) iif "wg0" ip saddr {{ peer.ip }} ip daddr 192.168.10.200 tcp dport 80 ct state new,established,related accept {% endfor %} # Retours vers le tunnel oif "wg0" ct state established,related accept } chain output { type filter hook output priority 0; policy accept; } } table ip nat { chain prerouting { type nat hook prerouting priority -100; # Satisfactory — DNAT WAN → serveur dédié sur gpu-01 # (joignable via 192.168.1.200 sans route vers 192.168.10.0/24) iif {{ wan_interface }} tcp dport { 7777, 8888 } dnat to 192.168.10.20 iif {{ wan_interface }} udp dport 7777 dnat to 192.168.10.20:7777 # (Anciens DNAT Internet :9081→Authentik / :9080→Guacamole retirés au # durcissement 2026-07-07 — tout passe par funklab.online HTTPS ci-dessous.) # funklab.online — Freebox 80/443 → Traefik (routage par sous-domaine + TLS) iif {{ wan_interface }} tcp dport { 80, 443 } dnat to 192.168.10.200 } chain postrouting { type nat hook postrouting priority 100; # NAT masquerade pour le LAN cluster oif {{ wan_interface }} ip saddr 192.168.10.0/24 masquerade # Clients VPN → LAN cluster : masquerade en IP s01 (retours garantis même si # un nœud ne route pas 10.99.0.0/24) oif {{ lan_interface }} ip saddr 10.99.0.0/24 masquerade } }