Informática Numaboa - Linux
iptables para iniciantes
Qui 1 Jan 2009 02:46 |
- Detalhes
- Categoria: Como fazer configurações
- Atualização: Quinta, 05 Julho 2012 19:10
- Autor: vovó Vicki
- Acessos: 19855
O iptables é uma ferramenta que pode ser usada para controlar o Netfilter das mais diversas distribuições Linux. O Netfilter é um firewall embutido no kernel do Linux 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 que podem ser 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 é descrita em 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 (colocar em 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 que eles alcancem 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 de eles entrarem no sistema, é mais fácil imaginar que eles possam ser alterados nesta área de pré-roteamento para 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 ou pela "correnteza" INPUT ou pela "correnteza" FORWARD. Os pacotes que estão apenas em trânsito são levados pela vertente FORWARD. Quanto ao sistema local, os pacotes que são destinados a ele chegam pela vertente INPUT e os pacotes produzidos por ele são enviados e transitam apenas pela vertente OUTPUT.
Quando os pacotes saem da "caixa preta" e ainda não abandonaram a máquina, eles ainda 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 (vertentes) 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 representam 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 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 modo verbose (-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.
Grande abraço da vó Vicki