iptables: regras avançadas de firewall Linux

iptables é o firewall de baixo nível do kernel Linux, UFW é apenas uma interface simplificada sobre ele. Para casos que o UFW não cobre (port forwarding, NAT, regras por interface específica, proteção anti-DDoS avançada), iptables direto é a ferramenta certa. Entender iptables também é essencial para depurar problemas de rede em servidores com Docker.

Conceitos: tables, chains e targets

Entender a estrutura do iptables antes de escrever regras:

bash
# Estrutura do iptables:
# TABLES (tabelas) → CHAINS (correntes) → RULES (regras) → TARGET (ação)

# Tables principais:
# filter  → filtragem de pacotes (INPUT, OUTPUT, FORWARD)
# nat     → tradução de endereços (PREROUTING, POSTROUTING, OUTPUT)
# mangle  → modificação de pacotes
# raw     → controle de rastreamento de conexões

# Chains da tabela filter (mais usada):
# INPUT    → pacotes destinados ao próprio host
# OUTPUT   → pacotes originados no próprio host
# FORWARD  → pacotes roteados pelo host (ex: VPN, bridge)

# Targets comuns:
# ACCEPT   → permitir o pacote
# DROP     → descartar silenciosamente
# REJECT   → descartar e notificar o remetente
# LOG      → registrar em syslog e continuar
# RETURN   → retornar à chain anterior

# Ver regras atuais:
sudo iptables -L -n -v --line-numbers          # tabela filter
sudo iptables -t nat -L -n -v --line-numbers   # tabela nat
sudo iptables -t mangle -L -n -v               # tabela mangle

# Contar regras:
sudo iptables -L INPUT -n -v | wc -l

Configuração base de segurança

Criar script de firewall com regras de produção:

bash
#!/bin/bash
# /etc/iptables/setup.sh — script de configuração do firewall

# Limpar todas as regras existentes:
iptables -F && iptables -X && iptables -Z
iptables -t nat -F && iptables -t nat -X
iptables -t mangle -F && iptables -t mangle -X

# Política padrão: DROP tudo, liberar explicitamente:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Permitir loopback:
iptables -A INPUT -i lo -j ACCEPT

# Permitir conexões estabelecidas e relacionadas (estado de conexão):
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Permitir ICMP (ping) com rate limit:
iptables -A INPUT -p icmp --icmp-type echo-request -m limit   --limit 1/s --limit-burst 3 -j ACCEPT

# SSH (ajuste a porta):
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW   -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW   -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# HTTP e HTTPS:
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT

# Logar e descartar o restante:
iptables -A INPUT -m limit --limit 5/min -j LOG   --log-prefix "iptables-DROP: " --log-level 7
iptables -A INPUT -j DROP

# Salvar regras (persistência):
sudo apt install iptables-persistent
sudo netfilter-persistent save

Proteção anti-DDoS e flood

Regras para mitigar ataques de volume e flood:

bash
# Proteção contra SYN flood (TCP):
iptables -A INPUT -p tcp --syn -m limit   --limit 100/s --limit-burst 200 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP

# Proteção contra UDP flood:
iptables -A INPUT -p udp -m limit   --limit 100/s --limit-burst 200 -j ACCEPT
iptables -A INPUT -p udp -j DROP

# Bloquear pacotes fragmentados (usado em ataques):
iptables -A INPUT -f -j DROP

# Bloquear pacotes XMAS (todos flags setados):
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP

# Bloquear pacotes NULL (nenhum flag setado):
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

# Proteção contra port scanning (furtivo):
iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST RST   -m limit --limit 1/s --limit-burst 2 -j ACCEPT
iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j DROP

# Limitar novas conexões por IP (anti-DDoS por IP):
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW   -m recent --set --name HTTPS
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW   -m recent --update --seconds 60 --hitcount 20 --name HTTPS -j DROP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

Port forwarding e NAT

Redirecionar portas com a tabela nat do iptables:

bash
# Habilitar IP forwarding no kernel:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf

# Redirecionar porta 80 → 8080 localmente (sem Nginx):
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 8080

# Redirecionar para outro servidor (gateway/proxy):
# Pacotes chegando na porta 80 → reencaminhar para 192.168.1.100:80
iptables -t nat -A PREROUTING -p tcp --dport 80   -j DNAT --to-destination 192.168.1.100:80
iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -j ACCEPT

# Masquerade (NAT de saída — para VPN/containers):
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

# Verificar regras NAT:
sudo iptables -t nat -L -n -v --line-numbers

# DOCKER-USER chain (para corrigir bypass do UFW pelo Docker):
# Bloquear acesso externo à porta 8080 do container (deixar apenas Nginx):
iptables -I DOCKER-USER -p tcp --dport 8080   ! -s 127.0.0.1 -j DROP

Persistência e monitoramento das regras

Garantir que as regras sobrevivam ao reboot e monitorar tráfego bloqueado:

bash
# Instalar iptables-persistent para salvar automaticamente:
sudo apt install iptables-persistent

# Salvar regras atuais:
sudo netfilter-persistent save
# Salvo em:
# /etc/iptables/rules.v4  → IPv4
# /etc/iptables/rules.v6  → IPv6

# Restaurar manualmente se necessário:
sudo iptables-restore < /etc/iptables/rules.v4

# Verificar serviço de persistência:
sudo systemctl status netfilter-persistent

# Monitorar tráfego bloqueado em tempo real:
sudo dmesg | grep "iptables-DROP" | tail -20
sudo journalctl -k | grep "iptables-DROP" | tail -20

# Estatísticas de tráfego por regra (bytes/pacotes):
sudo iptables -L -n -v | sort -k 2 -n -r | head -20

# Resetar contadores de estatísticas:
sudo iptables -Z

# Script de monitoramento de IPs bloqueados:
sudo journalctl -k --since "1 hour ago" |   grep "iptables-DROP" |   grep -oP 'SRC=K[^ ]+' |   sort | uniq -c | sort -rn | head -10

Não quer configurar manualmente?

Implante o VPS Linux em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

nftables é o sucessor do iptables, mais eficiente, sintaxe mais limpa, tabelas e chains em um único comando, melhor suporte a IPv4+IPv6 simultaneamente. Ubuntu 20.04+ usa nftables por padrão como backend do iptables (iptables é um wrapper sobre nftables). Para novos setups: nftables nativo. Para compatibilidade com scripts existentes e Docker (que usa iptables diretamente): iptables ainda é necessário. UFW 0.36+ suporta nftables como backend.

DROP: descarta o pacote silenciosamente, o remetente espera pelo timeout (sem resposta). REJECT: descarta e envia RST/ICMP port-unreachable, o remetente sabe imediatamente que a porta está fechada. Para segurança: DROP é melhor, não confirma ao scanner que o host existe ou que a porta está fechada. Para usabilidade: REJECT é melhor, aplicações legítimas falham mais rápido sem esperar timeout. Compromise: DROP na política padrão (desconhecido), REJECT para serviços internos conhecidos.

Docker adiciona chains próprias: DOCKER, DOCKER-USER, DOCKER-ISOLATION-STAGE-1, DOCKER-ISOLATION-STAGE-2. Quando você mapeia uma porta (-p 8080:80), o Docker adiciona regras em DOCKER e PREROUTING/nat que abrem a porta diretamente, bypassing o UFW. A solução: (1) usar DOCKER-USER chain para regras que Docker respeita; (2) bind apenas em localhost (-p 127.0.0.1:8080:80) e usar Nginx como proxy; (3) usar redes Docker internas sem port mapping externo.

Sim, UFW gerencia as chains ufw-user-input e ufw-user-forward. Regras iptables diretas nas chains INPUT, OUTPUT, FORWARD coexistem. A ordem importa: pacotes percorrem as chains na ordem das regras, parando na primeira que dá match. Quando regras conflitam, a mais específica deve vir primeiro. Cuidado: sudo ufw reset apaga apenas as regras do UFW, não as diretas do iptables. Use sudo iptables -L para ver o estado completo.

Cada pacote percorre todas as regras até encontrar um match, o impacto aumenta linearmente com o número de regras. Para centenas de regras: impacto negligenciável em servidores modernos. Para milhares de regras (grandes infraestruturas): use ipset para gerenciar listas de IPs (O(1) vs O(n)) e nftables que tem performance melhor por design. Para VPS típico com 20-30 regras: overhead de firewall é < 0.1% da latência de rede.