Gerenciar a filtragem de pacotes com iptables

LinuxBeginner
Pratique Agora

Introdução

iptables é uma interface de linha de comando para gerenciar regras de filtragem de pacotes no Linux. Embora muitas distribuições modernas implementem essas regras por meio de um backend nftables, os administradores ainda encontram tarefas e sistemas existentes que utilizam a sintaxe do comando iptables.

Um modelo útil para iniciantes é imaginar o firewall como uma lista de verificação ordenada. Um pacote entra em uma cadeia, cada regra verifica se o pacote corresponde a condições como interface, protocolo ou porta, e um destino, como ACCEPT ou REJECT, determina o que acontece. A cadeia INPUT trata dos pacotes destinados ao host local. Como as regras são avaliadas de cima para baixo, tanto o conteúdo quanto a posição de uma regra são importantes.

Neste laboratório, você trabalhará com um único serviço web local e fará alterações estritamente limitadas à sua porta TCP. Você inspecionará o firewall atual, adicionará uma regra que rejeita solicitações, comprovará o efeito usando tráfego real, substituirá a regra por uma permissão explícita e removerá a regra criada pelo laboratório sem limpar nem reescrever o estado não relacionado do firewall.

Inspecionar o firewall e testar o serviço

Nesta etapa, você identificará a implementação do iptables instalada e confirmará que o serviço de teste local funciona antes de alterar qualquer regra do firewall.

Acesse o diretório do projeto para que todos os comandos posteriores sejam executados a partir do espaço de trabalho do curso.

cd /home/labex/project

Use command -v para localizar o executável que o shell executará.

command -v iptables

Essa verificação é mais útil do que simplesmente presumir que um comando está instalado: ela mostra o caminho resolvido do executável, normalmente /usr/sbin/iptables, e retorna um status diferente de zero se o shell não conseguir encontrá-lo.

Exiba as informações de versão e do backend. Neste host Ubuntu, a saída normalmente inclui nf_tables; isso significa que a sintaxe conhecida do iptables é convertida para o backend moderno do conjunto de regras do kernel.

sudo iptables --version

Você deverá ver uma saída semelhante a:

iptables v1.8... (nf_tables)

O nome do backend não altera os comandos usados neste laboratório. Você continuará criando e inspecionando regras com iptables; a implementação se encarrega de representá-las no kernel.

Antes de filtrar a porta, consulte o endpoint de saúde do serviço. Uma resposta bem-sucedida comprova que a aplicação está pronta; assim, uma falha posterior poderá ser atribuída à regra do firewall.

curl --noproxy '*' --fail --silent http://127.0.0.1:18086/health

Aqui, 127.0.0.1 é o endereço IPv4 de loopback, portanto o tráfego sai e retorna pela interface local lo, sem alcançar uma rede externa. --noproxy '*' impede que as configurações de proxy redirecionem a solicitação, --fail faz com que erros HTTP produzam um status de falha e --silent oculta o indicador de progresso, facilitando a leitura da resposta do serviço.

O serviço retorna:

iptables filter service ready

Inspecionar a cadeia INPUT e adicionar uma regra de rejeição

Nesta etapa, você examinará a cadeia INPUT atual e inserirá uma regra precisa para rejeitar o tráfego TCP de loopback destinado à porta de teste.

A opção -S exibe as regras em um formato semelhante a comandos. Especificar INPUT limita a saída aos pacotes destinados a este host.

sudo iptables -S INPUT

A primeira linha normalmente mostra a política da cadeia, por exemplo, -P INPUT ACCEPT. Essa política é a ação de fallback usada somente quando nenhuma regra anterior toma uma decisão final. As linhas seguintes, iniciadas por -A INPUT, correspondem às regras atualmente adicionadas à cadeia.

Para obter uma visão operacional, -L lista a cadeia, -n evita a resolução de nomes, que pode ser lenta, e --line-numbers mostra a posição de cada regra. A ordem é importante porque o primeiro destino final correspondente determina o resultado do pacote.

sudo iptables -L INPUT -n --line-numbers

Essas duas visualizações têm finalidades diferentes: -S é conveniente quando você precisa reutilizar a sintaxe de uma regra, enquanto -L é mais útil para consultar posições, contadores de pacotes e um resumo operacional rápido.

Insira a regra do laboratório na posição 1 usando -I INPUT 1. Ela corresponde à interface de loopback lo, ao protocolo TCP e à porta de destino 18086. O destino REJECT com tcp-reset recusa a conexão imediatamente, em vez de fazer o cliente esperar até que o tempo limite de um pacote descartado seja atingido.

sudo iptables -I INPUT 1 -i lo -p tcp --dport 18086 -j REJECT --reject-with tcp-reset

Leia o comando da esquerda para a direita: -i lo restringe a interface de entrada, -p tcp seleciona o protocolo, --dport 18086 seleciona o serviço e -j REJECT encaminha o processamento para o destino de rejeição. -I insere a regra em uma posição escolhida; já -A adicionaria a regra ao final, onde uma regra correspondente anterior poderia impedir que ela fosse alcançada. Essa combinação restrita evita bloquear portas ou interfaces externas não relacionadas.

REJECT e DROP não são idênticos. REJECT envia uma resposta de erro, enquanto DROP descarta o pacote silenciosamente. Um reset TCP faz com que este teste local falhe de maneira rápida e previsível, facilitando o diagnóstico em comparação com a espera por um tempo limite.

Use -C para verificar se essa regra exata existe. Uma verificação bem-sucedida termina com status zero. Neste host, a implementação baseada em nftables também exibe a regra de correspondência normalizada; outras implementações podem terminar silenciosamente.

sudo iptables -C INPUT -i lo -p tcp --dport 18086 -j REJECT --reject-with tcp-reset

O resultado portável de -C é o status de saída, não a presença ou ausência de texto na tela. Isso torna o mesmo comando útil em scripts de shell e verificações automatizadas.

Liste a cadeia novamente. A nova regra deverá aparecer como regra 1 e mencionar tcp dpt:18086.

sudo iptables -L INPUT -n --line-numbers

Verificar o tráfego bloqueado

Nesta etapa, você repetirá a solicitação original e examinará os contadores da regra para comprovar que o firewall, e não a aplicação, rejeitou o tráfego.

Execute a solicitação dentro de uma instrução if. Como é esperado que a solicitação falhe, o ramo else transforma essa falha esperada em uma mensagem clara, permitindo que o fluxo guiado continue.

if curl --noproxy '*' --fail --silent http://127.0.0.1:18086/health; then
  echo "Unexpected: request succeeded"
else
  echo "Expected: iptables rejected the request"
fi

As condicionais do shell tomam decisões com base no status de saída de um comando: zero seleciona then, enquanto um valor diferente de zero seleciona else. O reset enviado pelo firewall faz com que curl retorne um valor diferente de zero; portanto, alcançar o ramo else é o resultado esperado aqui.

A mensagem esperada é:

Expected: iptables rejected the request

Agora liste a cadeia com -v para exibir os contadores detalhados. As contagens de pacotes e bytes na regra da porta 18086 deverão ser maiores que zero após a solicitação.

sudo iptables -L INPUT -n -v --line-numbers

Na saída, a coluna pkts contabiliza os pacotes correspondentes e a coluna bytes contabiliza o tamanho combinado deles. Os contadores são evidências úteis: verificar com -C comprova que a regra existe, enquanto o aumento do contador comprova que o tráfego real chegou à regra e correspondeu a ela. Se o contador continuar em zero, verifique a interface, o protocolo, a porta e a posição da regra antes de atribuir o problema à aplicação.

Substituir a regra de rejeição por uma regra de permissão

Nesta etapa, você excluirá a regra de rejeição exata, adicionará uma regra de permissão explícita para o mesmo tráfego e verificará se o acesso foi restabelecido.

A forma -D abaixo identifica a regra por meio de sua correspondência e destino completos. Isso é mais seguro do que limpar a cadeia, pois remove apenas a alteração pertencente ao laboratório.

sudo iptables -D INPUT -i lo -p tcp --dport 18086 -j REJECT --reject-with tcp-reset

As regras também podem ser excluídas pelo número da linha, mas os números mudam sempre que regras são inseridas ou removidas. Excluir pela especificação exata é mais claro em um procedimento repetível e reduz a possibilidade de remover uma regra vizinha. Evite iptables -F aqui: a limpeza removeria todas as regras da cadeia selecionada, inclusive as que não têm relação com este laboratório.

Insira uma regra ACCEPT para a mesma interface, protocolo e porta.

sudo iptables -I INPUT 1 -i lo -p tcp --dport 18086 -j ACCEPT

ACCEPT permite que um pacote correspondente continue pela pilha de rede. A regra é inserida na posição 1 para que seu resultado não seja ocultado por uma regra final anterior. Observe que a correspondência continua tão restrita quanto antes; somente o destino foi alterado.

Verifique a regra de permissão exata.

sudo iptables -C INPUT -i lo -p tcp --dport 18086 -j ACCEPT

Repita a solicitação de saúde original.

curl --noproxy '*' --fail --silent http://127.0.0.1:18086/health

A resposta está disponível novamente:

iptables filter service ready

Remover a regra pertencente ao laboratório

Nesta etapa, você removerá a regra temporária de permissão e confirmará que nenhuma regra deste exercício permanece.

Exclua a regra ACCEPT exata. Como antes, isso não limpa a cadeia nem altera regras pertencentes à plataforma ou a outro administrador.

sudo iptables -D INPUT -i lo -p tcp --dport 18086 -j ACCEPT

Remover uma regra de permissão explícita não significa automaticamente que o serviço será bloqueado. Depois que a regra desaparece, as regras restantes e, por fim, a política da cadeia determinam o destino do pacote. Neste ambiente preparado, o firewall original permite a solicitação local.

Verifique novamente a existência da regra. Desta vez, a falha é esperada; por isso, || executa a mensagem à direita somente quando iptables -C retorna um status diferente de zero.

sudo iptables -C INPUT -i lo -p tcp --dport 18086 -j ACCEPT 2>/dev/null || echo "Lab allow rule removed"

Você deverá ver:

Lab allow rule removed

Por fim, confirme que a remoção da regra explícita não interrompeu a aplicação. A política e as regras originais da cadeia voltam a determinar o acesso.

curl --noproxy '*' --fail --silent http://127.0.0.1:18086/health

Resumo

Você inspecionou a implementação do iptables e a cadeia INPUT, inseriu e verificou uma regra de rejeição restrita, comprovou seu efeito usando tráfego real e contadores, substituiu-a por uma regra de permissão e removeu apenas a alteração pertencente ao laboratório. Essas operações oferecem a prática necessária, em nível de comando, para trabalhar com filtragem de pacotes com segurança, sem limpar o estado não relacionado do firewall.