O iptables é uma ferramenta que pode ser usada para controlar o Netfilter de várias distribuições Linux. O Netfilter é um firewall embutido no kernel e o iptables é uma ferramenta que permite estabelecer regras para este firewall.
Este tutorial trata apenas dos aspectos básicos das tabelas do iptables e da sintaxe para a criação de regras.
O Netfilter
Como você já deve saber, toda comunicação numa rede TCP-IP é feita através de pacotes. O Netfilter trata apenas de regras. Estas regras são aplicadas aos pacotes. Cada regra é criada para fazer alguma coisa, e esta coisa é chamada de alvo. As regras pertencem a vertentes (chains), que são usadas para agrupar regras. Imagine as vertentes como uma correnteza que carrega pacotes, onde cada vertente leva determinado tipo de pacote. Cada vertente pertence a uma tabela.
Alvos das Regras
Como já disse, as regras atuam sobre os pacotes. Se uma regra for aplicável a um pacote, então o alvo é executado. Os alvos pré-existentes são ACCEPT (aceitar), DROP (descartar), QUEUE (fila de espera) e RETURN (retornar ou devolver).
As cinco vertentes pré-existentes
Imagine seu sistema como uma caixa preta. Fora desta caixa preta fica um processador que “caça” todos os pacotes destinados ao seu sistema antes mesmo deles alcançarem a interface de entrada – uma placa ethernet, um modem, uma antena de wireless ou qualquer outra interface de comunicação. Esta área é chamada de pré-roteamento. Como os pacotes não podem ser alterados pelo sistema antes deles entrarem no sistema, é mais fácil imaginar que eles possam ser alterados nesta área de pré-roteamento de modo que, quando alcançarem a interface, já tenham sido modificados e estejam prontos para serem roteados. Desta forma, as regras da vertente PREROUTING podem ser aplicadas antes que os pacotes entrem no sistema.
Dentro do sistema existem mais três vertentes: INPUT (entrada), FORWARD (redespacho) e OUTPUT (saída). Todos os pacotes que chegam são levados pela “correnteza” INPUT ou FORWARD. Os que estão apenas em trânsito são levados pela vertente FORWARD, os que são destinados para o sistema local vão pela vertente INPUT. Os pacotes provenientes do sistema local transitam apenas pela vertente OUTPUT.
Quando os pacotes saem da “caixa preta” e ainda não abandonaram a máquina, eles podem ser levados por uma última vertente – a POSTROUTING. Esta é a área de pós-roteamento, onde o sistema também não pode mais alcançar os pacotes.
As tabelas do iptables
O framework do iptables é dividido em 3 tabelas separadas:
- tabela filter,
- tabela nat (Network Address Translation – Tradução de Endereços de Rede) e
- tabela mangle (lustrar, dar brilho).
Cada uma destas tabelas possui correntes ou vertentes (chains) mostrando os caminhos que devem ser seguidos ou as tarefas que devem ser realizadas.
O filtro
A tabela filter é a tabela padrão e uma das mais utilizadas. É usada para identificar e tratar os pacotes que passam pelo firewall. Esta tabela possui três vertentes: INPUT (entrada), OUTPUT (saída) e FORWARD(redespacho), ou seja, é o coração da “caixa preta” do sistema. A vertente de entrada trata os pacotes destinados ao sistema local, a de saída filtra os pacotes que estão saindo do sistema local e a vertente de redespacho mostra o que deve ser feito com os pacotes que estão apenas em trânsito porque se destinam a outra máquina.
Um dado pacote não pode transitar por mais de uma vertente, ou seja, o pacote que estiver na “correnteza” INPUT não pode pular a a vertente FORWARD e vice-versa.
Se você quiser saber se sua máquina está ou não filtrando pacotes, chame o iptables para listar a tabela de filtragem com -L (lista). Se você ainda não definiu nenhuma regra de filtragem, o resultado mostra apenas as vertentes vazias:
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Nada impede identificar a tabela no comando usado: iptables -L -t filter tem o mesmo efeito que iptables -L.
A tabela NAT
Esta tabela é usada para alterar o endereço IP e/ou portas de destino. Suas vertentes são PREROUTING (pré-roteamento), POSTROUTING (pós-roteamento) e OUTPUT (saída).
Na vertente PREROUTING podemos identificar a origem do pacote (interface de entrada) além do endereço IP e a porta à qual se destina. Antes do pacote ser roteado (quando ainda está na área de pré-roteamento) podemos alterar o IP e também a porta que deve recebê-lo – em outras palavras, pode-se mudar a rota do pacote direcionando-o para uma outra máquina e/ou para uma outra porta na mesma máquina ou numa máquina diferente.
A vertente OUTPUT serve para dar saída aos pacotes e para analisá-los antes que saiam da máquina.
Na vertente POSTROUTING podemos alterar o IP/porta de origem do pacote. Também podemos indicar a interface de saída. Tudo isto acontece depois do pacote ter sido tratado na vertente OUTPUT e um pouquinho antes de ser despachado, ou seja, quando está na área de pós-roteamento.
Se você quiser saber se a sua máquina está redirecionando pacotes, chame o iptables com o comando -L -t nat. Se nenhuma regra tiver sido definida, a listagem deve ser a seguinte:
# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Apenas para reforçar: para listar a tabela NAT, é preciso especificá-la com a diretiva -t (tabela). No caso da tabela de filtragem isto não foi preciso porque o filtro é a tabela padrão do iptables.
A tabela mangle
Esta tabela serve para guardar as regras que devem ser seguidas para “escovar” (“lustrar”) pacotes, ou seja, fazer pacotes “mexidos”. Mas quem é que quer ou precisa dar uma ajeitada em pacotes? O motivo mais comum é alterar o campo Tipo de Serviço (Type Of Service – TOS). Este campo é lido pelo kernel do Linux e altera a prioridade do pacote.
Como o uso da tabela mangle é pequeno e depende de conhecimentos mais especializados, não vou entrar em maiores detalhes por que ainda temos muito pela frente.
Em todo caso, agora que você já sabe como descobrir as vertentes de uma tabela, que tal dar um iptables -L -t mangle?
Aprendendo na prática
O iptables disponibiliza uma série de comandos que podem ser “vitaminados” com um outro tanto de opções. Pelo menos um destes comandos nós já conhecemos, o -L, usado para listar tabelas. Se você tiver curiosidade, faça um iptables -h para ver o que pode ser feito:
iptables -h
iptables v1.3.3
Usage:
iptables -[AD] chain rule-specification [options]
iptables -[RI] chain rulenum rule-specification [options]
iptables -D chain rulenum [options]
iptables -[LFZ] [chain] [options]
iptables -[NX] chain
iptables -E old-chain-name new-chain-name
iptables -P chain target [options]
iptables -h (print this help information)
Commands:
Either long or short options are allowed.
–append -A chain Append to chain
–delete -D chain Delete matching rule from chain
–delete -D chain rulenum Delete rule rulenum (1 = first) from chain
–insert -I chain [rulenum] Insert in chain as rulenum (default 1=first)
–replace -R chain rulenum Replace rule rulenum (1 = first) in chain
–list -L [chain] List the rules in a chain or all chains
–flush -F [chain] Delete all rules in chain or all chains
–zero -Z [chain] Zero counters in chain or all chains
–new -N chain Create a new user-defined chain
–delete-chain -X [chain] Delete a user-defined chain
–policy -P chain target Change policy on chain to target
–rename-chain -E old-chain new-chain
Change chain name, (moving any references)
Options:
–proto -p [!] proto protocol: by number or name, eg. `tcp’
–source -s [!] address[/mask] source specification
–destination -d [!] address[/mask] destination specification
–in-interface -i [!] input name[+] network interface name ([+] for wildcard)
–jump -j target target for rule (may load target extension)
–match -m match extended match (may load extension)
–numeric -n numeric output of addresses and ports
–out-interface -o [!] output name[+]
network interface name ([+] for wildcard)
–table -t table table to manipulate (default: `filter’)
–verbose -v verbose mode
–line-numbers print line numbers when listing
–exact -x expand numbers (display exact values)
[!] –fragment -f match second or further fragments only
–modprobe=<command> try to insert modules using this command
–set-counters PKTS BYTES set the counter during insert/append
[!] –version -V print package version.
Observe que todos os comandos e opções possuem duas formas: a completa e a reduzida. Observe também que a forma reduzida dos comandos é sempre em letra maiúscula e a das opções é em letra minúscula e que a forma completa é precedida por — e a forma reduzida por -. Apenas para ficarmos no que já sabemos usar, para listar tabelas a forma completa é –list (dois hífens seguidos pela palavra list) e a forma reduzida é -L (um hífem seguido pela letra maiúscula L).
Criando a primeira regra
Se é que você não sabe, o endereço 127.0.0.1 é a interface ‘loopback’, a qual existe mesmo quando nenhuma conexão de rede estiver ativa. Vamos usá-la neste exemplo para criar pacotes.
O modo mais fácil e rápido de criar um pacote é usando o programa ‘ping’. O ping envia um pacote ICMP tipo 8 (requisição de eco) ao qual todos os hosts (máquinas) que estejam no mesmo segmento de rede precisam obrigatoriamente responder com um pacote ICMP tipo 0 (resposta de eco). Isto torna o programa muito útil para fazer testes de conectividade e… para fazer testes com o Netfilter/iptables.
Experimente o seguinte:
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.072 ms
— 127.0.0.1 ping statistics —
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.072/0.072/0.072/0.000 ms
A opção -c 1 (count 1 = contador 1) do ping diz para enviar apenas um pacote. Na estatística vê-se que apenas um pacote foi transmitido pela máquina local para ela mesma (1 packets transmitted), que ela recebeu a resposta (1 received) e que, portanto, houve 0% de perda de pacotes (0% packet loss).
Agora chegou a hora de botar o firewall para funcionar. Como não queremos alterar o pacote de resposta ao ping antes que ele alcance o sistema, podemos esquecer a área de pré-roteamento e nos concentrarmos apenas no sistema. Sabemos que este pacote não vai ser redespachado (afinal, é a resposta que estamos esperando) e que, se está endereçado para nossa máquina, só pode ser levado pela vertente INPUT (entrada). Quais são as tabelas que possuem a vertente INPUT? A tabela filter e a tabela mangle (a nap não tem a vertente INPUT). A mangle é para alterar características do pacote, nada do que pretendemos fazer. Só sobra a tabela filter.
Eu poderia ter explicado esta coisa toda dizendo que, como queremos filtrar um pacote ICMP vindo de 127.0.0.1, vamos usar a tabela filter. Acontece que repetir a lógica do sistema Netfilter/iptables nunca é demais. Existem casos um pouco mais complicados que apenas podemos resolver se conhecermos o caminho das pedras (ou o caminho da “correnteza”). Pelo menos foi assim que eu aprendi a pilotar este firewall.
Mas vamos lá, está na hora de criar nossa primeira regra. Vamos chamar o iptables para acionar a tabela filter (-t filter) e adicionar (-A) na vertente INPUT uma regra que diz: quando o endereço de origem (-s source) for 127.0.0.1 e o protocolo (-p) for icmp, salte (-j jump) para DROP (descartar). Bão, para escrever isto em iptablês, faça o seguinte:
# iptables -t filter -A INPUT -s 127.0.0.1 -p icmp -j DROP
É claro que a opção -t filter poderia ser omitida (já que a tabela filter é a default), mas, por uma questão de respeito (e para deixar as coisas mais explícitas), resolvi identificar a tabela. Para verificar o resultado deste comando, faça uma listagem com iptables -t filter -L INPUT ou apenas com iptables -L INPUT:
# iptables -t filter -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP icmp — localhost anywhere
Veja que a política é aceitar qualquer pacote que venha “boiando” nesta vertente (policy ACCEPT), a não ser que se encaixe em qualquer uma das regras que vier a seguir. A única regra é a que acabamos de criar e ela diz que, se o pacote for do protocolo ICMP (prot icmp), originário de localhost (source localhost) que é o mesmo que 127.0.0.1 e cujo destino for para qualquer lugar (destination anywhere), o alvo (target) é DROP (descartar). Isto significa que, a partir de agora, qualquer resposta de ping será descartada. Toca conferir:
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
— 127.0.0.1 ping statistics —
1 packets transmitted, 0 received, 100% packet loss, time 0ms
Fazendo um novo ping, igualzinho ao primeiro, até parece que tudo travou. Tenha paciência, demora um pouquinho mesmo. Depois do pacote de resposta do ping chegar levado pela vertente INPUT, nossa regra precisa ser aplicada e o pacote é descartado. Tanto é que a resposta é 1 packets transmitted, 0 received, 100% packet loss.
Novamente, só para conferir, vamos pedir uma listagem apenas da vertente INPUT da tabela filter no modoverbose (-v explicativo) e com número de linhas (–line-numbers):
# iptables -t filter -L INPUT -v –line-numbers
Chain INPUT (policy ACCEPT 5592 packets, 2716K bytes)
num pkts bytes target prot opt in out source destination
1 1 84 DROP icmp — any any localhost anywhere
O modo verbose diz que um pacote (pkts 1) foi recebido e descartado. Dê mais um ping e confira que pkts vai para 2. Não é que funciona mesmo?
Mais um exemplo de regra
Quando um usuário chama seu site com HTTP://www.seusite.com.br, a porta 80 é automaticamente acionada. Só para efeito de teste, vamos adicionar mais uma porta de acesso para o site, a 8080.
Antes de começar, experimente acessar seu site com http://www.seusite.com.br:8080. A não ser que a porta 8080 esteja habilitada, você vai receber uma página de erro informando que houve falha na conexão. Se não há conexão, então vamos proporcioná-la usando o iptables… só para testar.
Vamos redirecionar a porta 8080 para a porta 80. Redirecionar significa rotear de forma diferente e a tabela que cuida disto é a NAT. Com uma regra na vertente PREROUTING podemos alterar todos os pacotes cujo protocolo seja TCP trocando a porta de destino de 8080 para 80. A sintaxe deste comando é a seguinte:
iptables -t nat -A PREROUTING -p {protocolo} -i {interface} -d {IP destino}
–dport {porta destino} -j REDIRECT –to-port {nova porta}
Podemos usar todas as opções ou algumas delas. Neste exemplo nos interessam apenas as opções -t (precisamos garantir que a tabela seja a nat), -p, –dport e –to-port. Para adicionar a nova regra faça o seguinte:
iptables -t nat -A PREROUTING -p tcp –dport 8080 -j REDIRECT –to-port 80
Só pra tirar a cisma, chame seu site novamente com http://www.seusite.com.br:8080 e… é isto aí. Funcionou novamente.
Eliminando regras
Como este segundo exemplo é uma insanidade (ninguém vai chamar seu site usando a porta 8080), não tem sentido manter esta regra no Netfilter. É isto mesmo o que você leu, o iptables é uma ferramenta que coloca as regras diretamente dentro do Netfilter, ou seja, no kernel do Linux. Bem, se ele serve para adicionar regras, o esperado é que também seja capaz de retirá-las. O comando para retirar regras do Netfilter é especialmente importante de se conhecer quando estamos brincando com o firewall – caso alguma coisa dê errado ou não esteja de acordo com o esperado, precisamos poder eliminar a regra para podermos continuar com nossas experiências. O comando para limpar as tabelas chama-se Flush e meu mnemônico é F de Faxina:
iptables -F
iptables -t nat -F
iptables -t mangle -F
Por um lado, o -F da faxina é bom porque tira TODAS as regras de determinada tabela; por outro, é uma encrenca quando queremos eliminar apenas uma delas. Para remediar existe um outro comando, o -D de deletar, que precisa de um parâmetro adicional: o número da regra que queremos fazer sumir. Digamos que nossa tabela NAT tenha 5 regras na vertente PREROUTING. Para saber como estão numeradas é só listar a tabela com a opção –line-number:
iptables -t nat -L PREROUTING –line-number
Depois disto, basta indicar o número da regra que deve ser eliminada com:
iptables -t nat -D PREROUTING 3
Uma outra forma de eliminar determinada regra é simplesmente repetir o que ela estava ditando. Digamos que criamos uma regra do tipo iptables -A INPUT -s 192.168.0.1 -j ACCEPT. Para eliminá-la da tabela filter é só repetir a regra depois do -D:
iptables -D INPUT -s 192.168.0.1 -j ACCEPT
Tornando as regras permanentes
O fato de inserirmos regras no Netfilter usando o iptables não significa que elas são permanentes – enquanto o servifor estiver no ar, tudo bem; no momento em que for rebootado, ba-bau… as regras estarão perdidas. Como fazer com que sejam recuperadas? Coloque as regras num dos scripts de inicialização do boot (por exemplo, no /etc/rc.d/rc.local). É isso aí.
Finalmentes
O básico do básico sobre o iptables é o que você acabou de ler. É claro que a coisa não pára por aí. Há um mundo de comandos e opções que ainda pode ser explorado, mas isto vai ficar por sua conta. Espero que este texto introdutório sirva de ajuda para poder começar. O resto fica por sua conta.
Boa noite
Parabenizar pela introdução de iptables,muito boa bem explicada e rica em detalhes desmestificados.
Sou iniciante com iptables tenho minha rede domestica modesta mas é o que tenho não trabalho com Linux mas quem sabe algum dia é um objetivo,enquanto este dia não chega voubuscando conhecimento garimpando aqui ali.
Tenho uma pergunta ?
Qual regra de firewall com iptables é indispensavel para qualquer rede doméstica ou organizacional,você determina algo indispensavel que tem que ter logo de imediato,uma regra que não pode faltar nunca em firewall iptables?
Gostaria de saber par proteção própria,pois gostei muito do artigo que tem muita propriedade e fiquei curioso pois poderia adotala,como sou novo com o iptables fiquei curioso.
Obrigado ,atenciosamente Robson
Bom amigo… digamos assim…. acho que você deve definir o que quer proteger.
Em uma rede doméstica usando apenas estações Windows, sem servidores acho que o mais importante de protejer da internet são as portas dos protocolos Windows… tipo 137, 139, 445 entre outras.
Em uma coorporação o importante e juntar funcionalidade com segurança. Não adianta ninguem conseguir fazer nada.
Cada porta aberta e fechada deve ser bem estudada para ver seu impacto no trabalho e na produtividade dos colaboradores.