Se você trabalha com infraestrutura Linux, sabe que uma atualização de kernel deveria ser algo rotineiro. Mas, às vezes, um "plugin desgramado" de segurança ou uma atualização automática decide instalar um kernel novo e, de repente, seu firewall para de falar com o kernel. Foi exatamente o que aconteceu comigo recentemente em um servidor Rocky Linux 8.10.
Vou compartilhar o sufoco e a solução técnica para que você não perca o mesmo tempo que eu.
1. O diagnóstico inicial: o erro de incompatibilidade do kernel#
Tudo começou quando precisei adicionar uma regra de NAT simples para um container Docker:
# O comando que deveria funcionar:
/usr/sbin/iptables -w10 -t nat -A DOCKER -p tcp --dport 38888 -j DNAT --to-destination 192.168.x.x:8888 ! -i br-generica
O retorno foi um soco no estômago: iptables: No chain/target/match by that name.
Tentei listar as regras e o erro mudou para algo ainda mais preocupante: iptables: Incompatible with this kernel.
Ao rodar um uname -r, vi que estava no kernel 4.18.0-553.97.1.el8_10.x86_64. Era uma versão recente que um plugin de anti-intrusão tinha forçado no sistema.
O problema é que o Rocky Linux 8 (assim como o RHEL 8) usa o nftables como backend. O binário iptables é apenas uma camada de compatibilidade. Quando o kernel atualiza e essa camada "quebra", geralmente é porque:
- O kernel e as ferramentas de rede saíram de sincronia.
- Os módulos de NAT (
iptable_nat,nf_nat) não foram instalados para essa versão específica do kernel.
No meu caso, ao tentar carregar o módulo manualmente: modprobe: FATAL: Module nft_chain_nat_ipv4 not found in directory /lib/modules/4.18...
Bingo! O kernel novo estava lá, mas os "músculos" (os módulos, especificamente o pacote -modules-extra) não foram instalados junto. O kernel estava "capado".
2. Auditoria e histórico do DNF#
Antes de corrigir o problema, é essencial entender o histórico do gerenciador de pacotes para ver exatamente qual atualização quebrou os módulos:
# 1. Verificar o histórico de transações do dnf
dnf history list
# 2. Ver detalhes da última atualização de kernel (substitua <ID> pelo ID da transação correspondente)
dnf history info <ID>
# 3. Verificar quais pacotes de módulos de kernel estão atualmente instalados
rpm -qa | grep kernel-modules
3. Backup preventivo de regras iptables#
Antes de reinstalar os pacotes e recarregar os módulos do kernel, faça um backup completo das tabelas de firewall do sistema para evitar perda de configurações personalizadas:
# 1. Backup das regras atuais IPv4
sudo iptables-save > /root/iptables-backup-$(date +%Y%m%d).rules
# 2. Backup das regras atuais IPv6
sudo ip6tables-save > /root/ip6tables-backup-$(date +%Y%m%d).rules
# 3. Caso precise reverter as regras em caso de anomalia:
# sudo iptables-restore < /root/iptables-backup-$(date +%Y%m%d).rules
4. Verificação de módulos disponíveis e carregados#
Precisamos verificar se os pacotes extras de módulos estão disponíveis nos repositórios para o kernel ativo, e quais módulos estão de fato em memória:
# 1. Listar módulos extras disponíveis para a versão do kernel ativa
dnf list available kernel-modules-$(uname -r) kernel-modules-extra-$(uname -r)
# 2. Verificar módulos de rede atualmente carregados
lsmod | grep -E "iptable|nf_nat|br_netfilter|ip_tables"
# 3. Confirmar se o arquivo do módulo existe fisicamente no diretório de módulos do kernel
ls /lib/modules/$(uname -r)/kernel/net/netfilter/ | grep nat
5. A solução: instalando módulos extras e corrigindo o kernel#
Se o reboot para um kernel anterior falhar (como detalhado na Seção 10), a única saída é instalar os pacotes faltantes diretamente na versão do kernel rodando.
# Passo 1: Instalar os módulos de kernel e módulos extras que foram negligenciados
dnf install kernel-modules-$(uname -r) kernel-modules-extra-$(uname -r) -y
# Passo 2: Forçar o carregamento dos módulos em tempo de execução
modprobe iptable_nat
modprobe nf_nat
modprobe br_netfilter
6. Verificação pós-carregamento dos módulos#
Após carregar manualmente os módulos, valide se o kernel restabeleceu a comunicação correta com o xtables/iptables:
# 1. Verificar se os módulos aparecem como carregados
lsmod | grep -E "iptable_nat|nf_nat|br_netfilter"
# 2. Executar uma listagem simples para ver se o erro de incompatibilidade sumiu
iptables -L -n
# 3. Verificar as chains específicas de encaminhamento do Docker
iptables -t nat -L DOCKER -n
# 4. Checar mensagens de erro ou logs de depuração do kernel
dmesg | grep -iE "nf_nat|iptable" | tail -n 10
7. Persistência do carregamento dos módulos pós-reboot#
Para garantir que os módulos necessários permaneçam carregados após reinicializações do servidor, crie um arquivo de configuração persistente no diretório de carregamento do systemd:
# 1. Criar o arquivo de include com os módulos obrigatórios
echo "iptable_nat" | sudo tee /etc/modules-load.d/iptables.conf
echo "nf_nat" | sudo tee -a /etc/modules-load.d/iptables.conf
echo "br_netfilter" | sudo tee -a /etc/modules-load.d/iptables.conf
# 2. Testar se o utilitário do systemd consegue interpretar as configurações
sudo systemd-modules-load --test
8. Verificação e status do firewalld#
No Rocky Linux, o daemon firewalld pode entrar em conflito com as manipulações manuais de regras no iptables ou com o redirecionamento automático do Docker.
# 1. Verificar o status atual do serviço firewalld
systemctl status firewalld
Abordagens de resolução:#
- Opção A: Desativar o firewalld (Recomendado para servidores que usam iptables nativo/Docker diretamente)
sudo systemctl stop firewalld
sudo systemctl disable firewalld
- Opção B: Mapear portas diretamente no Firewalld (Alternativa sem usar regras puras do iptables)
sudo firewall-cmd --zone=public --add-port=38888/tcp --permanent
sudo firewall-cmd --reload
9. Verificação de restrições do SELinux#
Políticas de segurança do SELinux configuradas de forma extremamente rígida podem impedir que o binário do iptables interaja com os hooks do kernel.
# 1. Verificar o modo de execução do SELinux
getenforce
# 2. Se estiver em Enforcing, faça um teste rápido temporário alternando para Permissive
sudo setenforce 0
# 3. Execute o comando iptables de teste. Se o erro sumir, o SELinux é o bloqueador.
# Restaure o SELinux imediatamente:
sudo setenforce 1
# 4. Investigar bloqueios associados ao iptables no log de auditoria
sudo ausearch -m avc -ts recent | grep iptables
10. Validação do Docker e rede host#
Com os módulos devidamente instalados e carregados, certifique-se de que a rede do Docker se restabeleceu por completo:
# 1. Reiniciar o serviço do Docker para recriar as chains do NAT
sudo systemctl restart docker
# 2. Verificar o status do daemon do Docker
systemctl status docker
# 3. Listar as redes e bridges do Docker
docker network ls
ip link show type bridge
# 4. Validar interfaces físicas e tabelas de roteamento ativos
ip addr show
ip route show
11. Roteiro de rollback completo do kernel (grubby)#
Se as correções falharem, a melhor saída temporária em produção é voltar para o kernel anterior funcional. O Rocky Linux usa o utilitário grubby para gerenciar a entrada padrão do GRUB.
# 1. Listar todas as entradas e índices de kernels disponíveis
grubby --info=ALL | grep -E "index|kernel"
# 2. Apontar o kernel anterior estável como boot padrão usando seu caminho absoluto
grubby --set-default=/boot/vmlinuz-4.18.0-553.80.1.el8_10.x86_64
# 3. Alternativamente, defina a entrada utilizando o index numérico
grubby --set-default-index=0
# 4. Verificar se a alteração foi aplicada com sucesso
grubby --default-kernel
Nota: Em ambientes VPS ou instâncias de nuvem, se as alterações não surtirem efeito, audite as configurações do carregador no /boot/grub2/grub.cfg ou certifique-se de que a console externa não está forçando um kernel via rede.
12. Prevenção e hardening: travamento do kernel#
Para evitar atualizações indesejadas no kernel durante execuções automáticas do DNF, instale o versionlock e adicione o pacote estável:
# 1. Instalar o plugin do versionlock
dnf install 'dnf-command(versionlock)' -y
# 2. Adicionar o kernel funcional à lista de exclusão
dnf versionlock add kernel-4.18.0-553.80.1.el8_10.x86_64
Depois de todo esse caminho, a regra de redirecionamento entrou de primeira:
iptables -w10 -t nat -A DOCKER -p tcp --dport 38888 ! -i br-0f2060aef134 -j DNAT --to-destination 192.168.192.3:8888
Se você passar por isso, não se desespere com o erro de "Incompatible kernel". Antes de formatar ou brigar com o GRUB, verifique se os módulos de rede estão realmente instalados para a versão que você está rodando.
Script de diagnóstico e saúde do iptables (diagnose-iptables.sh)#
Este script shell de suporte mapeia e audita todas as camadas de kernel, módulos de rede, e firewalls do Rocky Linux 8:
#!/bin/bash
# diagnose-iptables.sh
# Script de diagnóstico para erros do Iptables no Rocky Linux 8.
# Deve ser executado como root.
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0;37m'
log_info() { echo -e "[${GREEN}INFO${NC}] $1"; }
log_warn() { echo -e "[${YELLOW}WARN${NC}] $1"; }
log_error() { echo -e "[${RED}ERROR${NC}] $1"; }
# 1. Verificar privilégios
if [ "$EUID" -ne 0 ]; then
log_error "Este script precisa ser executado como root."
exit 1
fi
log_info "=== Iniciando Diagnóstico do Iptables no Rocky 8 ==="
log_info "Versão do Kernel ativo: $(uname -r)"
# 2. Listar Pacotes Instalados
log_info "--- Pacotes de Módulos do Kernel Instalados ---"
rpm -qa | grep kernel-modules || log_error "Nenhum pacote kernel-modules localizado."
# 3. Validar Status do Carregamento dos Módulos
log_info "--- Auditoria de Módulos de Rede ---"
for mod in iptable_nat nf_nat br_netfilter ip_tables; do
if lsmod | grep -q "$mod"; then
log_info " ✅ Módulo $mod: carregado na memória."
else
log_warn " ❌ Módulo $mod: NÃO carregado na memória."
fi
done
# 4. Validar Funcionamento do Binário Iptables
log_info "--- Teste de Execução do Iptables ---"
if iptables -L -n >/dev/null 2>&1; then
log_info " ✅ Binário do iptables está respondendo normalmente."
else
log_error " ❌ Binário do iptables falhou ou retornou incompatibilidade com o kernel."
fi
# 5. Validar NAT e Cadeia do Docker
log_info "--- Validação de Tabelas NAT e Docker ---"
if iptables -t nat -L >/dev/null 2>&1; then
log_info " ✅ Tabela NAT disponível."
if iptables -t nat -L DOCKER -n >/dev/null 2>&1; then
log_info " ✅ Chain DOCKER NAT localizada."
else
log_warn " ❌ Chain DOCKER NAT ausente. Redes do Docker podem estar inacessíveis."
fi
else
log_error " ❌ Tabela NAT indisponível."
fi
# 6. Status do Firewalld
log_info "--- Status do Firewalld ---"
if systemctl is-active firewalld >/dev/null 2>&1; then
log_warn " ⚠️ Firewalld está ativo e rodando. Conflitos com regras nativas podem ocorrer."
else
log_info " ✅ Firewalld inativo."
fi
# 7. Status do SELinux
log_info "--- Status do SELinux ---"
if command -v getenforce >/dev/null 2>&1; then
log_info " Modo do SELinux: $(getenforce)"
else
log_info " SELinux não instalado."
fi
# 8. Logs de Auditoria Recentes
log_info "--- Últimas mensagens do dmesg relacionadas a netfilter ---"
dmesg | grep -iE "nf_nat|iptable|netfilter" | tail -n 5 || echo "Sem mensagens no dmesg."
log_info "=== Diagnóstico Concluído ==="
Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.



Comentários
Participe da discussão abaixo.
0 comentários