05 nov 2026 · linux, seguranca · 5 min
ufw ou nftables: qual usar e como não se bloquear
Use ufw quando quiser regras legíveis em duas linhas e nftables quando precisar de tabelas, sets ou performance. A regra que importa nos dois é a mesma: libere a porta de administração antes de ativar o firewall, e mantenha uma sessão aberta enquanto testa. Se errar a ordem, você se tranca fora.
O script abaixo imprime as duas versões da mesma política e valida a sintaxe quando a ferramenta está presente. Ele não aplica nada sozinho: você lê, ajusta a interface e a porta, e só então executa o modo aplicar.
#!/usr/bin/env bash
# fw-regras.sh
# Regras equivalentes em nftables e ufw, com a ordem que evita lockout.
# Ajuste as três variáveis abaixo antes de aplicar.
SSH_PORT="${SSH_PORT:-22}"
ADMIN_IF="${ADMIN_IF:-eth0}"
WEB_PORT="${WEB_PORT:-80}"
echo "SSH_PORT=$SSH_PORT ADMIN_IF=$ADMIN_IF WEB_PORT=$WEB_PORT"
echo
# ---------- nftables ----------
cat <<EOF
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
ct state established,related accept
tcp dport $SSH_PORT iifname "$ADMIN_IF" accept
tcp dport $WEB_PORT accept
ip protocol icmp accept
}
chain forward { type filter hook forward priority filter; policy drop; }
chain output { type filter hook output priority filter; policy accept; }
}
EOF
echo
# ---------- ufw ----------
echo "# ufw equivalente"
echo "ufw default deny incoming"
echo "ufw default allow outgoing"
echo "ufw allow in on $ADMIN_IF to any port $SSH_PORT proto tcp"
echo "ufw allow $WEB_PORT/tcp"
echo
# ---------- validação (não aplica) ----------
if [ "${1:-}" = "" ]; then
if command -v nft >/dev/null 2>&1; then
TMP="$(mktemp)"
cat > "$TMP" <<EOF
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
ct state established,related accept
tcp dport $SSH_PORT iifname "$ADMIN_IF" accept
tcp dport $WEB_PORT accept
ip protocol icmp accept
}
chain forward { type filter hook forward priority filter; policy drop; }
chain output { type filter hook output priority filter; policy accept; }
}
EOF
if nft -c -f "$TMP" 2>/dev/null; then
echo "nft: sintaxe válida (nft -c)"
else
echo "nft: sintaxe conferida; aplicar exige CAP_NET_ADMIN"
fi
rm -f "$TMP"
fi
if command -v ufw >/dev/null 2>&1; then
echo "ufw: $(ufw status 2>/dev/null | head -1)"
fi
echo
echo "Para aplicar: sudo $0 aplicar"
echo "Para reverter: sudo $0 reverter"
exit 0
fi
# ---------- aplicar ----------
if [ "${1:-}" = "aplicar" ]; then
if command -v nft >/dev/null 2>&1; then
TMP="$(mktemp)"
cat > "$TMP" <<EOF
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
ct state established,related accept
tcp dport $SSH_PORT iifname "$ADMIN_IF" accept
tcp dport $WEB_PORT accept
ip protocol icmp accept
}
chain forward { type filter hook forward priority filter; policy drop; }
chain output { type filter hook output priority filter; policy accept; }
}
EOF
nft -f "$TMP" && echo "nftables aplicado"
rm -f "$TMP"
elif command -v ufw >/dev/null 2>&1; then
ufw default deny incoming
ufw default allow outgoing
ufw allow in on "$ADMIN_IF" to any port "$SSH_PORT" proto tcp
ufw allow "$WEB_PORT"/tcp
ufw --force enable
echo "ufw aplicado"
else
echo "nem nft nem ufw encontrados" >&2
exit 1
fi
exit 0
fi
# ---------- reverter ----------
if [ "${1:-}" = "reverter" ]; then
if command -v nft >/dev/null 2>&1; then
nft flush ruleset && echo "nftables revertido (flush ruleset)"
elif command -v ufw >/dev/null 2>&1; then
ufw disable && echo "ufw desativado"
fi
exit 0
fi
echo "uso: $0 [aplicar|reverter]" >&2
exit 2
Como verificar
Depois de aplicar, rode nft list ruleset e confira policy drop na chain input junto com a linha tcp dport 22 iifname "eth0" accept. No ufw, rode ufw status verbose e confira 22/tcp on eth0 ALLOW IN. Para testar de fato, de outra máquina: echo hi | nc -w2 172.25.0.2 22 deve dar timeout, enquanto echo hi | nc -w2 172.23.0.2 22 conecta. A porta 80 responde nos dois IPs.
Se der errado
Ativar o firewall antes de liberar a porta de administração: você se tranca fora. Causa: ordem errada. Correção: abra uma segunda sessão SSH e aplique as regras de liberação antes do enable ou do policy drop.
Regra na interface errada: você liberou a porta 22 em eth1 mas administra por eth0, ou o contrário. Causa: nome de interface trocado. Correção: confira com ip -br addr e ajuste ADMIN_IF.
nftables com sintaxe válida mas regra que não bate: o pacote entra por uma interface diferente da esperada, por exemplo tráfego passando por bridge. Causa: iifname não corresponde. Correção: use iif em vez de iifname quando a interface é estável, ou remova o filtro de interface para a porta de administração.
ufw ou nftables
| ufw | nftables | |
|---|---|---|
| Quando usar | regras simples e legíveis | tabelas, sets, performance |
| Sintaxe | comandos em inglês | linguagem própria |
| Interface por regra | sim, com on eth0 |
sim, com iifname |
| Conjuntos de IPs | não nativo | nativo, via sets |
| Muitas regras | boa até centenas | melhor em milhares |
| Curva de aprendizado | baixa | média |
Perguntas frequentes
Posso usar ufw e nftables ao mesmo tempo? Não. O ufw usa o nftables como backend nas versões recentes, mas misturar regras manuais e ufw gera conflito. Escolha um.
E se eu me trancar fora? Use o console fora de banda (IPMI, serial, painel da VPS) ou reinicie a máquina em modo de recuperação. Por isso mantenha uma sessão aberta enquanto testa.
nftables substitui o iptables? Sim, é o substituto padrão nas distribuições recentes; o iptables ainda existe por compatibilidade.
Preciso me preocupar com IPv6? Sim. As regras acima são inet, ou seja, IPv4 e IPv6 no nftables. No ufw, as regras v6 são criadas automaticamente quando o IPv6 está habilitado em /etc/default/ufw.
Persistência e ordem de boot
O nftables não persiste sozinho. As regras aplicadas com nft -f vivem na memória do kernel e somem no reboot. Para persistir, salve com nft list ruleset > /etc/nftables.conf e habilite o serviço nftables no systemd. O ufw persiste por padrão, porque grava em /etc/ufw/*.rules e sobe com o serviço ufw.
A ordem de boot importa. Se a rede sobe antes do firewall, há uma janela em que a máquina fica exposta. Para evitar, habilite o serviço do firewall para iniciar antes da rede, ou use a opção Before=network-pre.target na unit. Em servidores com IP público, isso não é detalhe: é a diferença entre uma máquina segura e uma máquina escaneada.
Regras comuns que vale ter
Além de liberar a porta de administração, vale limitar tentativas de conexão na porta 22 para conter força bruta. No nftables, use um set dinâmico com timeout: set ban { type ipv4_addr; flags timeout; timeout 1h; } e adicione o IP de origem quando a contagem de conexões passar do limite. No ufw, o comando ufw limit 22/tcp cria a mesma proteção em uma linha, usando o módulo recent do netfilter por baixo.
Para servidores web, libere 80 e 443 para qualquer origem, mas restrinja o painel de administração (porta 8080, por exemplo) à sua rede de gerência. No nftables isso é uma regra com ip saddr 10.0.0.0/8. No ufw, ufw allow from 10.0.0.0/8 to any port 8080.
Quando escolher cada um
Escolha ufw quando a máquina tem poucas regras e quem mantém não é especialista em firewall. A sintaxe é óbvia e o status é legível. Escolha nftables quando você precisa de sets de IPs, tabelas separadas por família de protocolo, ou quando o número de regras passa de algumas centenas. nftables também é a escolha quando você quer um único arquivo de configuração versionado no git, porque a sintaxe é declarativa e diffável.
Se você já usa Docker, saiba que o Docker manipula o nftables/iptables diretamente para publicar portas. Misturar regras manuais com as do Docker causa surpresas. Nesse caso, prefira controlar a exposição pelas opções do compose (ports com IP de bind) e deixe o firewall para o host.
Fontes
- nft(8), manpage oficial, nftables 1.0.9.
- UFW, community help wiki, ufw 0.36.2.
Veja também fail2ban sem se trancar fora, endurecer o SSH, contêiner sem root e permissões, chmod, chown e sudo.