first commit

This commit is contained in:
Rodrigo Bertoldo de Sousa Martins committed 2026-09-13 20:49:33 -03:00
commit 01d7cb1a80
34 files changed
+5723

No files matched your search

+155
View File
@@ -0,0 +1,155 @@
#!/usr/sbin/nft -f
# ==============================================================
# nftables.conf — server-mv
#
# Substitui a parte de firewall do rc.local antigo (iptables/ip6tables,
# antes espalhada entre rc.local e test.sh). Regras funcionalmente
# equivalentes, com os bugs já corrigidos:
# - sem "-j DROP" solto no meio da chain (o catch-all é só a policy)
# - sem duplicação de regra de porta única + multiport
# - anti-spoof de 192.168.0.0/16 restrito à interface WAN
# - chain PORTSCAN removida (nunca era populada, sempre morta)
#
# Vantagens sobre iptables/ip6tables para este caso:
# - um ruleset só cobre IPv4 e IPv6 (table inet), então não existe
# mais o risco de esquecer de espelhar uma regra do v4 pro v6
# - "flush ruleset" no topo faz o carregamento ser atômico: se o
# arquivo tiver erro de sintaxe, o `nft -f` falha ANTES de aplicar
# qualquer coisa — você nunca fica com um firewall pela metade
# (iptables -F seguido de regras que podem falhar no meio é o
# oposto disso)
# - meters (rate-limit por IP de origem) substituem o módulo
# "recent" do iptables com sintaxe mais legível
#
# Aplicar:
# nft -c -f nftables.conf # valida sintaxe sem aplicar
# nft -f nftables.conf # aplica
# systemctl enable --now nftables # persistência no boot
#
# Depois de migrar, pare de carregar iptables/ip6tables no boot
# (remova essa parte do rc.local — ver rc.local.new) para não ter
# duas ferramentas de firewall competindo pelo mesmo netfilter.
# ==============================================================
flush ruleset
table inet filter {
# --- Meters (rate limit com estado por IP de origem) ---
# (declarados via "meter" inline nas regras que os usam, mais abaixo)
chain input {
type filter hook input priority filter; policy drop;
iifname "lo" accept
ct state established,related accept
# ICMP/ICMPv6: 2º maior volume medido no host, avaliado cedo
# de propósito (dados reais: ~66k pacotes/dia, ficava por
# último na versão antiga em iptables).
ip protocol icmp jump icmpv4
meta l4proto ipv6-icmp jump icmpv6
# Pacotes TCP malformados / scanners óbvios
tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) \
meter bad_packets { ip saddr timeout 5m limit rate over 5/minute } drop
tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 \
meter bad_packets6 { ip6 saddr timeout 5m limit rate over 5/minute } drop
ip frag-off & 0x1fff != 0 drop # fragmentos IPv4 (equivalente a "iptables -f")
# Anti-spoof — só faz sentido vindo da WAN
iifname "enp0s6" ip saddr 192.168.0.0/16 drop
iifname "enp0s6" ip6 saddr fe80::/10 drop
iifname "enp0s6" ip6 saddr fd00::/8 drop
ip6 daddr ff00::/8 drop
# SYN flood (limite global, equivalente ao antigo limit 10/sec burst 24)
tcp flags syn limit rate 10/second burst 24 packets accept
tcp flags syn drop
# Rate limit de conexões novas na porta SSH (8117): no máx. 3
# tentativas novas por IP a cada 60s
tcp dport 8117 ct state new \
meter ssh_meter { ip saddr timeout 60s limit rate 3/minute } accept
tcp dport 8117 ct state new meter ssh_meter6 { ip6 saddr timeout 60s limit rate 3/minute } accept
tcp dport 8117 ct state new drop
# Túneis / VPN
iifname "wg0" accept
iifname "tun0" accept
udp dport 1194 accept
# Serviços expostos na WAN
iifname "enp0s6" tcp dport { 80, 443 } accept
iifname "enp0s6" udp dport { 32100, 32101, 32110, 32400 } accept
# DHCPv6 client
udp dport 546 accept
}
chain forward {
type filter hook forward priority filter; policy accept;
ct state established,related accept
iifname "tun0" accept
iifname "wg0" accept
tcp daddr 10.15.0.45 dport { 80, 443 } accept
tcp ip6 daddr 2001:db8:15::45 dport { 80, 443 } accept
}
chain output {
type filter hook output priority filter; policy accept;
}
chain icmpv4 {
icmp type echo-reply accept
icmp type echo-request limit rate 1/second burst 3 packets accept
icmp type echo-request drop
drop
}
chain icmpv6 {
icmpv6 type destination-unreachable accept
icmpv6 type packet-too-big limit rate 5/minute accept
icmpv6 type time-exceeded limit rate 5/minute accept
icmpv6 type echo-request limit rate 1/second burst 3 packets accept
icmpv6 type echo-request drop
icmpv6 type echo-reply accept
icmpv6 type nd-router-solicit accept
icmpv6 type nd-router-advert accept
icmpv6 type nd-neighbor-solicit accept
icmpv6 type nd-neighbor-advert accept
drop
}
}
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat;
iifname "enp0s6" tcp dport 80 dnat to 10.15.0.45:80
iifname "enp0s6" tcp dport 443 dnat to 10.15.0.45:443
}
chain postrouting {
type nat hook postrouting priority srcnat;
ip saddr 10.15.0.0/16 masquerade
ip saddr 172.17.0.0/16 masquerade
oifname "wg3" masquerade
# Hairpin NAT (clientes locais acessando o IP público)
oifname "enp0s6" ip daddr 10.15.0.45 tcp dport { 80, 443 } masquerade
}
}
table ip6 nat {
chain prerouting {
type nat hook prerouting priority dstnat;
iifname "enp0s6" tcp dport 80 dnat to [2001:db8:15::45]:80
iifname "enp0s6" tcp dport 443 dnat to [2001:db8:15::45]:443
}
chain postrouting {
type nat hook postrouting priority srcnat;
ip6 saddr 2001:db8:15::/48 masquerade
oifname "enp0s6" ip6 daddr 2001:db8:15::45 tcp dport { 80, 443 } masquerade
}
}