Linux 2.4 Filtro de Pacotes HOWTO <author>Rusty Russel, lista de email <tt>netfilter@lists.samba.org</tt> <date>Data: $Revision: 1.5 $ $Date: 2002/08/08 04:00:36 $ <abstract> Este documento descreve como usar o iptables para filtrar pacotes ruins nos Linux 2.4. </abstract> <!-- Tabela de conteúdo --> <toc> <!-- Início do Documento --> <sect>Introdução<label id="intro"> <p> Bem vindo, gentil leitor. <p> Neste artigo, assume-se que você saiba o que é um endereço IP, um endereço de rede, uma máscara de rede, e o que são o roteamento e o DNS. Se não for este o caso, eu recomendo que você leia o Conceitos de Redes Linux HOWTO. <p> Este HOWTO muda entre uma introdução gentil (que vai deixar você com um sentimento quente e gostoso agora, mas desprotegido no Mundo Real) e um desnudamento total (que irá deixar a todos, menos as almas mais duras, paranóicos e procurando por armamento pesado). <p> Sua rede não é <bf/segura/. O problema de permitir comunicação rápida e conveniente ao mesmo tempo que restringe seu uso para boas e não más intenções é congruente a outros problemas intratáveis como permitir a liberdade de expressão ao mesmo tempo que não se permite gritar ``Fogo!'' em um teatro cheio. E não será resolvido no espaço deste HOWTO. <p> Assim, só você pode decidir onde estará o compromisso. Eu tentarei instruir você no suo de algumas das ferramentas disponíveis, e algumas vulnerabilidades às quais deve-se prestar atenção, na esperança que você irá usar estas informações para objetivos nobres, e não maus. Outro problema equivalente. <p>(C) 2000 Paul `Rusty' Russel. Licenciado sob a GNU GPL. <sect>Onde está o Web Site oficial? Existe uma Lista de Email? <p> Existem três sites oficiais: <itemize> <item>Graças ao <url url="http://netfilter.filewatcher.org/" name="Filewatcher">. <item>Graças ao <url url="http://netfilter.samba.org/" name="The Samba Team e SGI">. <item>Graças ao <url url="http://netfilter.gnumonks.org/" name="Harald Welte">. </itemize> <p>Para a lista de email oficial do netfilter, veja o <url url="http://lists.samba.org/" name="Listserver do Samba">. <sect>O que é um Filtro de Pacotes? <p> Um filtro de pacotes é um software que fica examinando o <em/cabeçalho/ dos pacotes à medida que vão passando, e decide o destino de cada pacote. Ele pode decidir fazer um <bf/DROP/ (descartar) o pacote (isto é, descatar o pacote como se nunca houvesse recebido o mesmo), pode fazer um <bf/ACCEPT/ (aceitar) no pacote (isto é, deixar o pacote passar), ou fazer algo mais complicado. <p> No Linux, a filtragem de pacotes é montada no kernel (como um módulo, ou dentro do mesmo), e existem algumas poucas coisas complciadas que podemos fazer com os pacotes, mas o princípio geral de examinar os cabeçalhos e decidir o destino do pacote ainda está presente. <sect1>Por quê vou querer um Filtro de Pacotes? <p> Controle. Segurança. Vigilância. <p> <descrip> <tag/Controle:/ quando você está usando um computador Linux para conectar sua rede interna a outra rede (digamos, a Internet) você tem a oportunidade de permitir certos tipos de tráfego, e proibir outros. Por exemplo, o cabeçalho de um pacote contém o endereço de destino do pacote, assim você pode evitar que os pacotes venham a ir em certa parte da rede externa. Como um outro exemplo, eu uso o Netscape para acessar os arquivos do Dilbert. Existem propagandas da doubleclick.net na página, e o Netscape desperdiça o meu tempo baixando alegremente estas propagandas. Informando ao filtro de pacotes não permitir que nenhum pacot indo ou vindo dos endereços da doubleclick.net resolve este problema (existem outras formas melhores de fazer isto, veja o Junkbuster). <tag/Segurança:/ quando seu comptuador Linux é a única coisa entre o caos da Internet e sua pequena e bem ordenada rede, é bom saber que você pode restringir o que vem pela sua porta. Por exemplo, você pode permitri que tudo saia de sua rede, mas pode estar preocupado com o bem conhecido `Ping of Death' vindo de locais externos maliciosos. Como outro exemplo, você pode não querer que pessoas de fora façam telnet para seu computador Linux, mesmo que todas as tuas contas tenham senhas. Talvez você queira (como muitas pessoas) ser um observador da nternet, e não um servidor (voluntário ou não). Simplesmente não deixe qualquer um conectar-se, fazendo com que o filtro de pacotes rejeite pacotes que chegam que sejam usados para iniciar conexões. <tag/Vigilância/ algumas vezes uma máquina mal configurada na rede local decide espalhar pacotes para o mundo. É bom fazer com que o filtro de pacotes avise você se algo anormal ocorrer, talvez você possa fazer algo sobre isto, ou talvez você apenas seja curioso por natureza. </descrip> <sect1>Como eu faço Filtragem de Pacotes no Linux?<label id="filter-linux"> <p> Os kernel Linux tem suporte a filtro de pacotes desde a série 1.1. A primeira geração, baseada no ipfw do BSD, foi portada por Alan Cox no fim de 1994. Ela foi melhorada por Jos Vos e outros para o Linux 2.0; a ferramenta de userspace `ipfwadm' controlava as regras de filtro do kernel. No meio de 1998, para o Linux 2.2, eu refiz bastante o kernel, com a ajuda de Michael Neuling, e introduzi a ferramenta de userspace `ipchains'. Finalmente, a ferramenta de quarta geração, o `iptables', e outra reescrita de kernel, ocorreram na metade de 1999 para o Linux 2.4. É neste iptables que este HOWTO se concentra. <p> Você vai precisar um kernel que tenha a infraestrutura de netfilter nele: o netfilter é uma estrutura geral dentro do kernel Linux que outras coisas (como o módulo iptables) podem ligar. Isto significa que você precisará do kernel 2.3.15 ou posterior, e responder `Y' para a opção CONFIG_NETFILTER na configuração do kernel. <p> A ferramenta <tt/iptables/ fala com o kernel e informa ao mesmo quais pacotes devem ser filtrados. A menos que você seja um programador, ou uma pessoa muito curiosa, é asim que você irá controlar a filtragem de pacotes. <sect2>iptables <p> A ferramenta <tt/iptables/ insere e apaga regras da tabela de filtros de pacotes do kernel. Isto significa que, o que quer que você configure, será perdido no reboot. Veja <ref id="permanent" name="Tornando as Regras Permanentes"> para saber como fazer para que as regras sejam erstauradas na próxima vez que o Linux seja inicializado. <p> O <tt/iptables/ é uma ferramenta substituta do <tt/ipfwadm/ e do <tt/ipchains/: veja <ref id="oldstyle" name="Usando o ipchains e o ipfwadm"> para saber como evitar usar o iptables de forma indolor se você está usando uma destas ferramentas. <sect2>Tornando as Regras Permanentes<label id="permanent"> <p> Sua configuração de firewall atual está armazenada no kernel, e será perdida quando você reiniciar o computador. Você pode tentar os scripts iptables-save e iptables-restore para salvar e recuperar estas regras de um arquivo. <p> A outra forma é colocar os comandos necessários para configurar suas regras em um script de inicialização. Certifique-se de fazer alguma coisa inteligente se algum dos comandos falhar (usualmente `exec /sbin/sulogin'). <sect>Quem diabos é você, e por que você está brincando com meu kernel? <p>Eu sou Rusty Russel, o mantenedor do Linux IP Firewall e somente outro programador que aconteceu de estar no lugar certo na hora certa. Eu escrevi o ipchains (veja <ref id="filter-linux" name="Como eu faço Filtragem de Pacotes no Linux?"> acima para o crédito devido às pessoas que realmente fizeram o trabalho), e aprendeu o suficiente para conseguir fazer a filtragem de pacotes certa desta vez. Eu espero. <p> A <url url="http://www.watchguard.com" name="WatchGuard">, uma excelente companhia de firewalls que vende o plug-in realmente legal Firebox, ofereceu-se para pagar-me para não fazer nada, assim eu posso gastar todo meu tempo escrevendo estas coisas, e mantendo as coisas que já fiz. Eu previa um tabalho de 6 meses, e ele demorou 2, mas eu acho que no fim eu fiz tudo certo. Muitas reescritas, um problema de disco rígido, um laptop roubado, um par de filesystems corrompidos e uma tela quebrada mais tarde, e aqui está. <p> Enquanto estou aqui, eu quero esclarecer algums enganos: eu não sou um guru do kernel. Eu sei isto por que o meu trabalho no kernel me colocou em contato com alguns deles: David S. Miler, Alexey Kuznetsov, Andi Kleen, Alan Cox. Entretanto, todos eles estão ocupados fazendo a mágica mais profunda, me deixando para caminhar nas pontas rasas onde é mais seguro. <!-- Isto rpovaelmente não é mais verdade; em algum ponto escrevendo todo este código e documentação do kernel parece que eu acabei aprendendo um bom número de truques do kernel. Mas eu ainda não sou tão esperto como eu acho que sou. --> <sect>Guia Realmente Rápido do Rusty para Filtros de Pacotes <p> A maioria das pessoas tem uma única conexão PPP com a Internet, e não quer que niguém venha para dentrod e sua rede, ou do firewall: <tscreen><verb> ## Insira os módulos de acompanhamento de conexão (não necessários se ## estiverem dentro do kernel). # insmod ip_conntrack # insmod ip_conntrack_ftp ## Cria a cadeia que bloqueia novas conexões, exeto as que vem de dentro # iptables -N block # iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT # iptables -A block -m state --state NEW -i ! ppp0 -j ACCEPT # iptables -A block -f DROP ## Salta para aquela cadeia nas cadeias INPUT e FORWARD. # iptables -A INPUT -j block # iptables -A FORWARD -j block </verb></tscreen> <sect>Como os Pacotes Atravessam os Filtros <p> O kernel começa com tres listas de regras na tabela `filter'. Estas listas são chamadas de <bf/firwall chains/ (cadeias de firewall), ou só <bf/cadeias/. As três cadeias são chamadas <bf/INPUT/, <bf/OUTPUT/ e <bf/FORWARD/ (entrada, saída e repasse, respectivamente). <p> Para os fãs de ASCII-art, as cadeias são arranjadas assim: <bf>(Nota: este é um arranjo bastante diferente dos kernels 2.0 e 2.2!)</bf> <verb> _____ Entrando / \ Saindo -->[Decisão de]-->|FORWARD|-----> [Roteamento] \_____/ ^ | | v ____ ___ / \ / \ |OUTPUT| |INPUT| \____/ \___/ ^ | | ---> Processo Local --- </verb> <p> Os três círculos representam as três cadeias mencionadas acima. Quando um pacote atinge um círculo no diagrama, aquela cadeia é examinada para determinar o destino do pacote. Se a cadeia disser para descartar (DROP) o pacote, ele é morto ali, mas se a cadeia disser para aceitar (ACCEPT) o pacote, então ele continua no diagrama. <p> Uma cadeia é uma lista de <bf/regras/. Cada regra diz `se o cabeçalho do pacote se parecer com isto, então é isto o que você deve fazer com o pacote'. Se a regra não combinar com o pacote, então a próxima regra na cadeia é consultada. Finalmente, se não houver mais nenhuma regra a consultar, então o kernel examina a cadeia <bf/policy/ (política) para deicidir o que fazer. Em um sistema seguro, esta política geralmente diz ao kernel para descartar (DROP) o pacote. <p> <enum> <item>Quando um pacote chega (digamos, pela placa Ethernet) o kernel primeiro examina o destino do pacote: isto é chamado de `roteamento'. <item>Se ele está destinado a este computador, o pacote passa adiante no diagrama, para a cadeia INPUT. Se ele passar esta cadeia, qualquer processo que esteja aguardando pelo pacote o receberá. <item>Caso contrário, se o kernel não tem o repasse habilitado, ou ele não sabe como repassar o pacote, o pacote é descartado. Se o repasse estiver habilitado, e o pacote é destinado para outra interface de rede (se você tiver outra), então o pacote vai para a cadeia FORWARD. Se ele é aceito, ele será passado adiante. <item>Finalmente, um programa rodando no computador pode enviar pacotes de rede. Estes pacotes passam pela cadeia OUTPUT imediatamente: se ela disser para aceitar (ACCEPT), então o pacote continua para a interface de rede ele está destinado. </enum> <sect>Usando o iptables <p> O iptables possui uma página de manual bem detalhada (<tt/iptables/), e se você precisa de mais detalhes em aspectos específicos. Os que estão familiarizados com o ipchains podem simplesmente dar uma olhada em <ref id="Appendix-A" name="Diferenças Entre o iptables e o ipchains">; eles são bastante similares. <p> Existem várias coisas diferenes que você pode fazer com o <tt/iptables/. Você começa com as três cadeias internas, <tt/INPUT/, <tt/OUTPUT/ e <tt/FORWARD/ que você não pode apagar. Vamos dar uma olhada nas operações que tratam as cadeias inteiras: <enum> <item>Criar uma nova cadeia (-N). <item>Apagar uma cadeia vazia (-X). <item>Mudar a política para uma cadeia interna (-P). <item>Listar as regras de uma cadeia (-L). <item>Esvaziar as regras de uma cadeia (-F). <item>Zerar a contagem de pacotes e de bytes de todas as regras de uma cadeia (-Z). </enum> <p> Existem várias formas de manipular as regras dentro de uma cadeia: <enum> <item>Apensar uma nova regra em uma cadeia (-A). <item>Inserir uma nova regra em alguma posição da cadeia (-I). <item>Substituir uma regra em certa posição da cadeia (-R). <item>Apagar uma regra em uma determinada posição da cadeia (-D). <item>Apagar a primeira regra que atende a uma pesquisa em uma chain (-D). </enum> <sect1>O Que Você Verá Quando Seu Computador Inicializa <p> O iptables pode ser um módulo, chamado (`iptable_filter.o'), que deve ser carregado automaticamente quando você roda pela primeira vez o comando <tt/iptables/. Ele também pode ser inserido no kernel permanentemente. <p> Antes que qualquer comando iptables seja executado (atenção aqui: algumas distribuições rodam o iptables nos seus scripts de inicialização), não há nenhuma regra em qualquer uma das regras internas (`INPUT', `FORWARD' e `OUTPUT'), todas as regras tem como política ACCEPT. Você pode alterar a política defalut da cadeia FORWARD fornecendo a opção `forward=0' para o módulo iptable_filter. <sect1>Operações Em Uma Única Regra <p> Este é o feijão-com-arroz da filtragem de pacotes, a manipulação de regras. Geralmente você irá usar provavelmente os comandos para apensar (-A) e apagar (-D). Os outros (-I para inserir e -R para substituir) são simples extensões destes conceitos. <p> Cada regra especifica um conjunto de condições que um pacote deve atender, e o que fazer quando elas são atendidas (um `objetivo'). Por exemplo, você pode querer descartar todos os pacotes ICMP vindo do endereço IP 127.0.0.1. Neste caso, suas condições são qeu o protocolo deve ser o ICMP e que o endereço origem deve ser 127.0.0.1. O objetivo é `DROP'. <p> O endereço 127.0.0.1 é da interface `loopback', que você tem mesmo que não tenha uma conexão de rede real. Você pode usar o programa `ping' para gerar estes pacotes (ele simplesmente manda pacotes ICMP tipo 8 -- echo request, ou pedido de eco -- que todos os hosts cooperativos devem obrigatoriamente responder com um pacote ICMP tipo 0 -- echo reply, ou resposta de eco). Isto faz com que o ping seja útil para testes. <tscreen><verb> # ping -c 1 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms --- 127.0.0.1 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.2/0.2/0.2 ms # iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP # ping -c 1 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes --- 127.0.0.1 ping statistics --- 1 packets transmitted, 0 packets received, 100% packet loss # </verb></tscreen> Pode-se ver que o primeiro ping funciona bem (o `-c 1' informa ao ping para mandar somente um pacote). <p> Então anexamos (-A) na cadeia `INPUT', uma regra especificando que para pacotes vindo de 127.0.0.1 (`-s 127.0.0.1') com protocolo ICMP (`-p ICMP') devemos ir para DROP (`-j DROP'). <p> Quando testamos nossa regra, usamos o segundo ping. Há uma pausa antes que o programa desista de esperar uma resposta que nunca virá. <p> Podemos apagar a regra de duas formas diferentes. Primeiro, já que sabemos que é a única regra na cadeia de entrada, podemos usar uma exclusão numerada, como: <tscreen><verb> # iptables -D INPUT 1 # </verb></tscreen> Para apagar a regra número 1 na cadeia INPUT. <p> A segunda forma é repetir o comando -A, mas substituindo o -A por -D. Isto é útil quando você tem uma cadeia de regras complexas e você não quer contar elas até descobrir que é a regra 37 que você quer livrar-se. Neste caso, usaríamos: <tscreen><verb> # iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP # </verb></tscreen> A sintaxe do -D deve ter exatamente as mesmas opções do comando -A (ou -I ou -R). Se houver múltiplas regras idênticas na mesma cadeia, somente a primeira será excluída. <sect1>Especificações de Filtro <p> Vimos o uso do `-p' para especificar o protocolo, e o `-s' para especificar o endereço de origem, mas existem outras opções que opdemos usar para especificar características dos pacotes. O que segue é um compêndio exaustivo. <sect2>Especificando Endereços IP de Origem e Destino <p> Endereços IP de origem (`-s', `--source' ou `--src') e destino (`-d', `--destination' ou `--dst') podem ser especificados de quatro formas. A forma mais comum é usar o nome completo, como `localhost' ou `www.linuxhq.com'. A segunda forma é especificar o endereço IP como em `127.0.0.1'. <p> A terceira e quarta formas permitem que se especifique um grupo de endereços IP, como em 199.95.207.0/24' ou `199.95.207.0/255.255.255.0'. Ambos especificam qualquer endereço IP de 199.95.207.0 a 199.95.207.255, inclusive. Os dígitos após o `/' informam quais partes do endereço IP são significantes. `/32' ou `/255.255.255.255' são o padrão (especifica todo o endereço IP). Para especificar qualquer endereço IP, o `/0' pode ser usado, como em: <tscreen><verb> [ NOTA: `-s 0/0' é redundante ] # iptables -A INPUT -s 0/0 -j DROP # </verb></tscreen> Este é raramente usado, já que o efeito é o mesmo de não ter especificado a opção `-s'. <sect2>Especificando Inversão <p> Muitas flags, incluindo `-s' (ou `--source') e `-d' (`--destination') podem ter seus argumentos precedidos por `!' (prouncia-se `não') para combinar endereços que NÃO sejam iguais aos dados. Por exemplo, `-s ! localhost' combina qualuqer pacote que <bf/não/ venha de localhost. <sect2>Especificando o Protocolo <p> O protocolo pode ser especificado com a flag `-p' (ou `--protocol'). O protocolo pode ser um número (se você sabe os valores numéricos dos protocolos para o IP) ou um nome para os casos especiais de `TCP', `UDP' ou `ICMP'. Não faz diferença se o nome é dado em maiúsculas ou minúsculas, assim, `tcp' funciona tão bem quanto `TCP'. <p> O protocolo pode ser prefixado por um `!', para inverter o mesmo, com em `-p ! TCP', para especificar pacotes que <bf/não/ são TCP. <sect2>Especificando uma Interface <p> As opções `-i' (ou `--in-interface') e `-o' (ou `--out-interface') especificam o nome de uma <bf/interface/ a combinar. Uma interface é o dispositivo físico do qual o pacote vem (`-i') ou para onde está indo (`-o'). Você pode usar o comando `ifconfig' para listar as interfaces que estão `em pé' (ou seja, que estão funcionando no momento). <p> Pacotes que estejam atravessando a cadeia <tt/INPUT/ não tem uma interface de saída, assim, qualquer regra que use `-o' nesta cadeia jamais será usada. De forma semelhante, pacotes que estejam atravessando a cadeia <tt/OUTPUT/ não tem uma interface de entrada, e qualquer regra que use `-i' nesta cadeia nunca será usada. <p> Somente pacotes que estão atravessando a cadeia <tt/FORWARD/ possuem tanto a interface de entrada e a de saída. <p> É perfeitamente legal especificar uma interface que atualmente não exista, a regra não irá ser usada por nenhum pacote até que a interface seja levantada. Isto é extremamente útil para links PPP discados (usualmente a interface é <tt/ppp0/) e parecidos. <p> Como um aso especial, uma interface cujo nome termine com um `+' irá combinar todas as interaaces (existentes ou não) que começam com aquela string. Por exemplo, para especificar uma regra que combina todas as interfaces PPP, a opção <tt>-i ppp+</tt> seria usada. <p> O nome da interface poderia ser precedido por um `!' entre espaço, para combinar com pacotes que <bf/não/ combinem com a interface(s) especificada, como em <tt>-i ! ppp+</tt>. <sect2>Especificando Fragmentos <p> Algumas vezes um pacote é muito grande para ser colocado de uma vez na rede. Quando isto acontece, o pacote é dividido em <bf/fragmentos/, e enviado em múltiplos pacotes. A outra ponta remonta estes fragmentos para reconstruir o pacote inteiro. <p> O problema com os ftagmentos é que o fragmento inicial tem os campos do cabeçalho completos (IP + TCP, UDP e ICMP) para serem examinados, mas os pacotes subsequentes tem somente um subconjunto dos cabeçalhos (IP sem os campos de protocolo adicional). Assim, olhar dentro destes fragmentos subsequentes por cabeçalhos de protocoo (como é feito com as extensões TCP, UDP e ICMP) não é possível. <p>Se você estiver fazendo acompanhamento de conexões ou NAT, então todos os fragmentos serão ligados antes que atinjam o código de filtragem de pacotes, e você não precisa se preocupar com fragmentos. <p> Caso contrário, é importante entender como os fragmentos são tratados pelas regras de filtro. Qualquer regra de filtro que peça por informações que não tenhamos <em/não/ será usada. Isto significa que o primeiro gragmento é tratado como qualquer outro pacote. O segundo e seguintes não serão. Assim, uma regra <tt>-p TCP --sport www</tt> (especificando uma porta de origem `www') nunca irá tratar um fragmento (além do primeiro fragmento). Nem a regra oposta <tt>-p TCP --sport ! www</tt>. <p> Entretanto, você pode especificar uma regra especificamente para o segundo fragmento e fragmentos seguintes, usando a flag `-f' (ou `--fragment'). Também pode ser especificada uma regra que <em/não/ aplique-se ao segundo fragmento e seguintes, precedendo o `-f' com um `!'. <p> Usualmente é considerado seguro deixar o segundo fragmento e seguintes passarem, uma vez que o filtro irá afetar o primeiro fragmento, e assim o pacote não poderá ser reconstruído no host de destino. Entretanto, existem bugs conhecidos que permitem que se derrubem máquinas simplesmente enviando fragmentos. <p> Nota para os experts de rede: pacotes mal formados (pacotes TCP, UDP e ICMP muito pequenos para que o código do firewall leia as portas ou código e tipo ICMP) são descartados quando estes testes são tentados. O mesmo para fragmentos TCP que comecem na posição 8. <p> Como um exemplo, o código seguinte irá descartar qualquer fragmento que vá para 192.168.1.1: <tscreen><verb> # iptables -A OUTPUT -f -d 192.168.1.1 -j DROP # </verb></tscreen> <sect2>Extensões ao iptables: Novas Combinações <p> O <tt/iptables/ é <bf/extensível/, o que significa que tanto o kernel e a ferramenta iptables podem ser extendidos para dar novas funcionalidades. <p> Algumas destas extensões são padrão, e outras são mais exóticas. As extensões podem ser feitas por outras pessoas e distribuídas separadamente para um nicho de usuários. <p> As extensões do kernel normalmente são colocadas no subdiretório de módulos do kernel, como em /lib/modules/2.4.0-test10/kernel/net/ipv4/netfilter. Elas são carregadas sob demanda se seu kernel foi compilado com a opção CONFIG_KMOD, assim você não precisa inserir manualmente as mesmas. <p> As extensões ao programa iptables são bibliotecas compartilhadas que normalmente ficam em /usr/local/lib/iptables, apesar que as distribuições iriam colocar em /lib/iptables ou /usr/lib/iptables. <p> As extensões vem em dois tipos: novos destinos, e novas combinações (falaremos sobre novos destinos um pouco mais tarde). Alguns protocolos oferecem automaticamente novos testes: atualmente estes são TCP, UDP e ICMP, como mostrado abaixo. <p> Para estes você pdoerá especificar novos testes na linha de comando após a opção `-p', que irá carregar a extensão. Para novos testes explícitos, ue a opção `-m' para carregar a extensão, após o quê as opções extendidas estarão disponíveis. <p> Para obter ajuda sobre uma extensão, use a opção que a carrega (`-p', `-j' ou `-m') seguido por `-h' ou `--help', com, por exemplo: <tscreen><verb> # iptables -p tcp --help # </verb></tscreen> <sect3>Extensões TCP <p> As extensões TCP são automaticamente carregadas se é especificada `-o tcp'. Elas provêem as seguintes opções (nenhuma das quais para fragmentos): <p> <descrip> <tag>--tcp-flags</tag>Seguido por um `!' opcional, e duas strings de flags, permite que você faça filtros para flags TCP específicas. A primeira string de flags é a máscara: uma lista de flags que você quer examinar. A segunda string de flags informa quais devem ser configuradas. Por exemplo, <tscreen><verb> # iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DROP </verb></tscreen> Este exemplo indica que todas as flags devem ser examinadas (`ALL' é sinônimo de `SYN,ACK,FIN,RST,URG,PSH'), mas somente SYN e ACK devem estar setadas. Há também um argumento `NONE', significando nenhuma flag. <tag>--syn</tag> Opcionalmente precedida por um `!', é um atalho para `--tcp-flags SYN,RST,ACK SYN'. <tag>--source-port</tag> seguido por um `!' opcional, e então ou uma única porta TCP, ou um intervalo de portas. As portas podem ser nomes de portas, conforme são listadas em /etc/services, ou numéricas. Os intervalso são ou dois nomes de portas separados por um `:', ou (para especificar maior ou igual a uma dada porta) uma porta com um `:' apenso, ou (para especificar menor ou igual a uma dada porta) uma porta precedida por um `:'. <tag>--sport</tag> é um sinônimo para `--source-port'. <tag>--destination-port</tag> e <tag>--dport</tag> fazem o mesmo que as opções acima, só que especificam a porta destino, em vez da origem, para combinar. <tag>--tcp-option</tag> seguido por um `!' opcional, e um número, combina um pacote com uma opção TCP igual ao número. Um pacote que não tenha um cabeçalho TCP completo é destartado automaticamente se for feita uma tentativa para examinar usas opções TCP. </descrip> <sect4>Uma Explicação das Flags TCP <p> Às vezes é útil permitir conexões TCP em uma direção, mas não em outra. Por exemplo, você pode querer permitir conexões para um servidor WWW externo, mas não conexões que venham daquele servidor. <p> Uma abordagem ingênua seria bloquear conexões TCP vindo do servidor. Infelizmente, as conexões TCP exigem que os pacotes viajem em ambas as direções para funcionar. <p> A solução é bloquear somente os pacotes usados para solicitar uma conexão. Estes pacotes são chamados pacotes <bf/SYN/ (ok, tecnicamente eles são pacotes com a flag SYN setada, e RST e ACK resetadas, mas vamos chamá-los de pacotes SYN para resumir). Proibindo somente estes pacotes, podemos parar qualquer tentativa de conexão que lhes sigam. <p> A flag `--syn' é usada para isto: ela é somente válida para regras que especificam o TCP como seu protocolo. Por exemplo, para especificar tentativas de conexão TCP de 192.168.1.1 <tscreen><verb> -p TCP -s 192.168.1.1 --syn </verb></tscreen> <p> Esta flag pode ser invertida precedendo a mesma com um `!', o que significa todos os pacotes que não o início de conexão. <sect3>Extensões UDP <p> Estas extensões são automaticamente carregadas se for especificada `-p udp'. Elas prevêem as opções `--source-port', `--sport', `--destination-port' e `--dport', conforme detalhado para o TCP, acima. <sect3>Extensões ICMP <p> Esta extensão é automaticamente carregada se for especificada `-p icmp'. Ela somente suporta uma nova opçõa: <p> <descrip> <tag>--icmp-type</tag> seguido por um `!' opcional, e então um nome de tipo icmp (por exemplo `host-unreachable'), ou um tipo numérico (por exemplo, `3'), ou um tipo numérico e um código separado por uma `/' (por exemplo, `3/3'). Uma lista de nomes de tipos icmp disponíveis é dada usando `-p icmp --help'. </descrip> <sect3>Outras Extensões Para Combinar <p> As outras extensões no pacote netfilter são extensões de demonstração, que (se instaladas) podem ser carregadas com a opção `-m'. <descrip> <tag>mac</tag> Este módulo deve ser explicitamente especificado com `-m mac' ou `--match mac'. É usada para selecionar endereços Ethernet (MAC) de pacotes que chegam, e somente é útil para pacotes que estejam atravessando as cadeias PREROUTING e INPUT. Ela somente dá estas opções: <descrip> <tag>--mac-source</tag>seguida por um `!' opcional, e um endereço ethernet na notação de hexabytes separadas por dois-pontos, como `--mac-source 00:60:08:91:CC:B7'. </descrip> <tag>limit</tag>Este módulo deve ser explicitamente especificado com `-m limit' ou `--match limit'. Ele é usado para restringir a taxa de combinação, como para suprimir mensagens de log. Ele somente irá combinar um dado número de vezes por segundo (por padrão 3 combinações por hora, com um burst de 5). Ela usa dois argumentos opcionais: <descrip> <tag>--limit</tag>seguido por um número; especifica o número médio máximo de combinações que são permitidas por segundo. O número pode especificar as unidades de forma explícita, usando `/second', `/minute', `/hour' ou `/day', ou partes delas (assim, `5/second' é o mesmo que `5/s'). <tag>--limit-burst</tag>seguido por um número, indicando o burst máximo antes que o limite acima é disparado. </descrip> Esta combinação pode ser usada geralmente com o destino LOG para efetuar um log limitado por uma taxa. Para entender como isto funcioan, vamos dar uma olhada na seguinte regra, que faz o log dos pacotes com os parâmetros default limites: <tscreen><verb> # iptables -A FORWARD -m limit -j LOG </verb></tscreen> Na primeira vez que a regra é atingida, o pacote será logado. De fato, desde que o burst padrão é 5, os primeiros 5 pacotes serão logados. Depois disto, levará mais vinte minutos antes que um pacote seja logado por esta regra, independente de quantos pacotes chegarem. Além disto, a cada vinte minutos que se passarem sem um pacote combinando, um dos burst será recuperado. Se nenhum pacote disparar a regra por 100 minutos, o burst será completamente recarregado. De volta para onde iniciamos. <p> Nota: Você não pode criar uma regra com um tempo de recarga maior que 59 horas, assim se você configurar uma taxa média de um por dia, então sua taxa de burst será menor que 3. <p> Você pode também usar este módulo para evitar vários ataques de negação de serviço (DoS) com uma taxa mais rápida para aumentar a responsividade. <p> Proteção contra syn-flood: <tscreen><verb> # iptables -A FORWARD -p tcp -sym -m limit --limit 1/s -j ACCEPT </verb></tscreen> Port-scanner furtivo: <tscreen><verb> # iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT </verb></tscreen> Ping da Morte: <tscreen><verb> # iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT </verb></tscreen> Este módulo é como uma "porta de histerese", como mostrado no gráfico abaixo. <tscreen><verb> taxa (pkt/s) ^ .---. | / DoS \ | / \ Lim. do DoS -|.....:.........\....................... = (limit * | /: \ limit-burst) | / : \ .-. | / : \ / \ | / : \ / \ Fim do DoS -|/....:..............:.../.......\..../. = limit | : :`-' `--' -------------+-----+--------------+------------------> tempo(s) LOGICA => Comb. | Não Combina | Combina(Match) </verb></tscreen> <p> Digamos que vamos combinar um pacote por segundo com um burst de cinco pacotes, mas os pacotes começam a vir quatro por segundo, por três segundos, e iniciam novamente em outros três segundos. <tscreen><verb> <--Flood 1--> <---Flood 2---> Total ^ Taxa __-- YNNN Pacotes| Linha __-- YNNN | mum __-- YNNN 10 | Maxi __-- Y | __-- Y | __-- Y | __-- YNNN |- YNNN 5 | Y | Y Chave: Y -> Combinou a regra | Y N -> Não combinou a regra | Y |Y 0 +--------------------------------------------------> Tempo(segundos) 0 1 2 3 4 5 6 7 8 9 10 11 12 </verb></tscreen> Você pode ver que os primeiros cinco pacotes tem permissão de exceder o limite de um pacoet por segundo, e então o limite entra em funcionamento. Se hovuer uma pausa, outro burst recebe permissão para passar, mas não passam a taxa máxima configurada pela regra (1 pacote por segundo depois que o burst é usado). <tag>owner</tag>Este módulo tenta combinar várias características do criador do pacote, para pacotes gerados localmente. Ele somente é válido na cadeia OUTPUT, e mesmo ali, alguns pacotes (como uma resposta ICMP a um ping) podem não ter nenhum dono, e assim não combinar. <descrip> <tag>--uid-owner userid</tag> Combina se o pacote foi criado por um processo com o id de usuário efetivo (numérico) fornecido. <tag>--gid-owner groupid</tag> Combina se o pacote foi criado por um porcesso com o id de grupo efetivo (numérico) fornecido. <tag>--pid-owner processid</tag> Combina se o pacote foi criado por um processo com o id de processo fornecido. <tag>--sid-owner sessionid</tag> Combina se o pacote foi criado por um proceso no grupo de sessão fornecido. </descrip> <tag>unclean</tag>Este módulo experimental deve ser especificado explicitamente com `-m unclean' ou `--match unclean'. Ele faz vários testes de sanidade aleatórios nos pacotes. Este módulo não foi auditado, e não deve ser usado como um dispositivo de segurança (ele provavelmente torna as coisas piores, já que deve ter bugs). Ele não aceita opções. </descrip> <sect3>A Combinação State <p> O critério de seleção mais útil é fornecido pela extensão `state', qu einterpreta a análise de acompanhamento de conexão do módulo `ip_conntrack'. Ela é altamente recomendada. <p> Especificando `-m state', é permitido uma opção adicional `--state', que é uma lista separada por vírgulas dos estados a selecionar (a flag `!' indica que <bf/não/ devem ser selecionados aqueles estados). Os estados são: <descrip> <tag>NEW</tag>Um pacote que cria uma nova conexão. <tag>ESTABLISHED</tag>Um pacote que pertence a uma conexão existente (um pacote de resposta, ou pacote de sa´dia de uma conexão que já recebeu respostas). <tag>RELATED</tag>Um pacote que é relacionado a, mas não parte de, uma conexão existente, como um erro ICMP, ou (com o módulo de FTP inserido), um pacote estabelecendo uma conexão de dados ftp. <tag>INVALID</tag>Um pacote que não pode ser identificado por alguma razão: estas incluem falta de memória e erros ICMP que não correspondam a nenhuma conexão conhecida. Geralmente estes pacotes devem ser descartados. </descrip> <sect1>Especificação de Destino <p> Agora que já sabemos os exames que podemos fazer em um pacote, precisamos de uma forma de dizer o que fzer com os pacotes selecionados pelos nossos testes. É o que chamamos de <bf>destino</bf> (target) da regra. <p> Existem dois destinos internos bem simples: DROP e ACCEPT. Nós já os vimos. Se uma regra seleciona um pacote e seu destino é um destes dois, nenhuma regra a mais é consultada: o destino do pacote já foi decidido. <p> Existem dois tipos de destinos além dos internos: extensões e cadeias definidas pelo usuário. <sect2>Cadeias Definidas pelo Usuário <p> Uma funcionalidade poderosa que o <tt/iptables/ herda do <tt/ipchains/ é a capacidade que o usuário tem de criar novas cadeias, aléma das três cadeias internas (INPUT, FORWARD e OUTPUT). Por convenção, as cadeias criadas pelo usuário são em minúsculas para distinguir as mesmas (iremos descrever como são criadas novas cadeias definidas pelo usuário mais abaixo, em <ref id="chain-ops" name="Operações em Cadeias Inteiras">). <p> Quando um pacote é selecionado por uma regra cujo destino é uma cadeia definida pelo usuário, o pacote começa a atravessar as regras naquela cadeia definida pelo usuário. Se a cadeia não decidir o destino do pacote, então assim que o caminhamento daquela cadeia terminar, o caminhamento prossegue na próxima regra da corrente atual. <p> Hora de uma ASCII art. Considere duas cadeias (bobas): <tt/INPUT/ (a cadeia interna) e <tt/test/ (uma cadeia definida pelo usuário). <tscreen><verb> `INPUT' `test' ---------------------------- ---------------------------- | Rule1: -p ICMP -j DROP | | Rule1: -s 192.168.1.1 | |--------------------------| |--------------------------| | Rule2: -p TCP -j test | | Rule2: -d 192.168.1.1 | |--------------------------| ---------------------------- | Rule3: -p UDP -j DROP | ---------------------------- </verb></tscreen> <p> Considere um pacote TCP vindo de 192.168.1.1, indo para 1.2.3.4. Ele entra na cadeia <tt/INPUT/, e é testado contra a regra Rule1 - não é selecionado. A Rule2 combina, e seu destino é <tt/test/, então a próxima regra a ser examinada é o início de <tt/test/. A regra Rule1 em <tt/test/ combina, mas naõ especifica um destino, então a regra seguinte é examinada, Rule2. Ela não combina, e chegamos ao fim da cadeia. Retornamos para a cadeia <tt/INPUT/, onde acabamos de examinar a regra Rule2, então iremos examinar a regra Rule3, que também não combina. <p> Assim, o caminho percorrido pelo pacote é: <tscreen><verb> v __________________________ `INPUT' | / `test' v ------------------------|--/ -----------------------|---- | Rule1 | /| | Rule1 | | |-----------------------|/-| |----------------------|---| | Rule2 / | | Rule2 | | |--------------------------| -----------------------v---- | Rule3 /--+___________________________/ ------------------------|--- v </verb></tscreen> <p> Cadeias definidas pelo usuário podem comandar saltos para outras cadeias definidas pelo usuário (mas não crie loops: seus pacotes serão descartados se forem encontrados em um loop). <sect2>Extensões ao iptables: Novos Destinos <p> O outro tipo de extensão é o destino. Uma extensão de destindo consiste de um módulo de kernel, e uma extensão opcional ao <tt/iptables/ para fornecer novas opções de linha de comando. Existem várias extensões na distribução padrão do netfilter: <descrip> <tag>LOG</tag>Este módulo faz o log a nível de kernel dos pacotes que forem selecionados. Ela permite as seguintes opções adicionais: <descrip> <tag>--log-level</tag>Seguido por um número de nível ou nome. Os nomes válidos são (independente de maiúsculas/minúsculas) `debug', `info', `warning', `err', `crit', `alert' e `emerg', correspondendo aos números 7 a 0. Veja a página man do syslog.conf para uma explicação sobre estes níveis. <tag>--log-prefix</tag>Seguido por uma string de até 29 caracteres, esta mensagem é enviada no início da mensagem de log, permitindo que a mesma seja indetificada unívoca. </descrip> Este módulo é mais útil após uma seleção de limite, de forma a não sobrecarregar os logs. <tag>REJECT</tag>Este módulo tem o mesmo efeito que o `DROP', exceto que o originador do pacote ercebe uma mensagem de erro ICMP `port unreachable' (porta não encontrada). Note que a mensagem de erro ICMP não é enviada se (veja a RFC 1122): <itemize> <item>O pacote sendo filtrado era uma mensagem de erro ICMP em primeiro lugar, ou um tipo ICMP desconhecido. <item>O pacote sendo filtrado não é um fragmento inicial. <item>Enviamos muitas mensagens de erro ICMP para aquele destino recentemente. </itemize> O REJECT também aceita um argumento opcional `--reject-with' que altera o pacote de resposta usado: veja a página de manual. </descrip> <sect2>Destinos Internos Especiais <p> Existem dois destinos internos especiais: <tt/RETURN/ e <tt/QUEUE/. <p> O <tt/RETURN/ possui o mesmo efeito de cair no fim de uma cadeia: para uma regra em uma cadeia interna, a política da cadeia é executada. Para uma regra em uma cadeia definida pelo usuário, o pacote passa para a cadeia anterior, na regra posterior à regra que saltou para aquela cadeia. <p> O <tt/QUEUE/ é um destino especial, que enfileira o pacote para processamento por programas do userspace. Para isto ser útil, dois componentes a mais são necessários; <itemize> <item>um "tratador de fila", que trata com os mecanismos reais de passar pacotes entre o kernel e o userspace; e <item>uma aplicação de userspace que recebe, possivelmente manipula, e determina vereditos sobre os pacotes. </itemize> O tratador de fila padrão para o iptables IPv4 é o módulo ip_queue, que é distribuído com o kernel e marcado como experimental. <p> A seguir há um rápido exemplo de como usar o iptables para enfileirar pacotes para processamento no userspace: <tscreen><verb> # modprobe iptable_filter # modprobe ip_queue # iptables -A OUTPUT -p icmp -j QUEUE </verb></tscreen> Com esta regra, pacotes ICMP gerados localmente saído (como os criados pelo ping, por exemplo) são passados para o módulo ip_queue, que então tenta entregar os pacotes a uma aplicação no userspace. Se nenhuma aplicação no userspace está esperando, os pacotes são descartados. <p> Para escrever uma aplicação de userspace, use a API libipq. Esta é distribuída com o iptables. Um código de exemplo pode ser encontrada nas ferramentas de teste (como, por exemplo, redirect.c) no CVS. <p> O status de ip_queue pode ser verificado via: <tscreen><verb> /proc/net/ip_queue </verb></tscreen> O comprimento máximo da fila (ou seja, o número de pacotes despachados para o userspace sem veredito devolvido) pode ser controlado via: <tscreen><verb> /proc/sys/net/ipv4/ip_queue_maxlen </verb></tscreen> O valor padrão para o tamanho máximo da fila é 1024. Uma vez que este limit seja atingido, novos pacotes serão descartados até que o comprimento da fila cai abaixo do limite novamente. Protocolos legais como o TCP interpretam pacotes descartados como congestão, e provavelmente irão aguardar quando a fila fica cheia. Entretanto, pode exigir algum experimento para determinar um tamanho de fila máximo ideal para uma dada situação se o valor padrão é muito pequeno. <sect1>Operações em Cadeias Inteiras<label id="chain-ops"> <p> Uma funcionalidade bastante útil do <tt/iptables/ é a capaciade de agrupar regras relacionadas em cadeias. Você pode dar o nome que quiser às cadeias, mas eu recomendo usar nomes em minúsculas para evitar confusão com as cadeias e destinos internos. Nomes de cadeias podem ter até 31 caracteres de comprimento. <sect2>Criando uma Nova Cadeia <p> Vamos criar uma nova cadeia. Como eu sou uma pessoa bastante criativa, eu vou chamar ela de <tt/test/. usamos a opção `-N' ou `--new-chain': <tscreen><verb> # iptables -N test # </verb></tscreen> <p> É assim simples. Agora você pode inserir regras como foi mostrado acima. <sect2>Apagando uma Cadeia <p> Apagar uma cadeia é simples também, usando as opções `-X' ou `--delete-chain'. Por quê `-X'? Todas as letras legais já foram usadas. <tscreen><verb> # iptables -X test # </verb></tscreen> <p> Existe um par de restrições para apagar uma cadeia: elas devem estar vazias (veja <ref id="flushing" name="Esvaziando uma Cadeia"> abaixo) e elas não devem ser o destino de nenhuma regra. Você não pode apagar nenhuma das três cadeias internas. <p> Se você não especificar uma cadeia, então <em/todas/ as cadeias definidas pelo usuário serão apagadas, se possível. <sect2>Esvaziando uma Cadeia<label id="flushing"> <p> Existe uma forma simples de esvaziar todas as regras de uma cadeia, usando o comando `-F' (ou `--flush'). <tscreen><verb> # iptables -F FORWARD # </verb></tscreen> <p> Se você não especificar uma cadeia, então <em/todas/ as cadeias serão esvaziadas. <sect2>Listando uma Cadeia <p> Você pode listar todas as regras em uma cadeia usando o comando `-L' (ou `--list'). <p> O `refcnt' listado para cada cadeia definida pelo usuário é o número de regras que tem aquela cadeia como seu destino. Este número tem que ser zero (e a cadeia deve estar vazia) antes que esta cadeia possa ser apagada. <p> Se o nome da cadeia é omitido, todas as cadeias são listadas, mesmo as vazias. <p> Aqui estão três opções que podem acompanhar o `-L'. A opção `-n' (numérica) é bastante útil por evitar que o <tt/iptables/ tente verificar os endereços IP, que (se você está usando o DNS como a maioria das pessoas) irá causar grandes demoras se seu DNS não estiver configurado corretamente, ou se você filtrou as solicitações DNS. Ele também faz com que as portas TCP e UDP sejam escritas como números em vez de nomes. <p> A opção `-V' mostra todos os detalhes sobre as regras, como os contadores de pacotes e bytes, comparações de TOS, e as interfaces. caso contrário estes valores são omitidos. <p> Note que os contadores de pacotes e bytes são escritos usando os sufixos `K', `M' ou `G' para 1.000, 1.000.000, e 1.000.000.000 respectivamente. usando a opção `-x' (expandir números) os números serão impressos completos, não importando o quão grandes sejam. <sect2>Reinicializando (Zerando) Contadores <p> É útil poder reiniciar os contadores. Isto pode ser feito com a opção `-Z' (ou `--zero'). <p> Considere o seguinte: <tscreen><verb> # iptables -L FORWARD # iptables -Z FORWARD # </verb></tscreen> No exemplo acima, alguns pacotes podem passar entre os comandos `-L' e `-Z'. Por esta razão, você pode usar o `-L' e `-Z' <em/juntos/, para reiniciar os contadores ao mesmo tempo que lê os mesmos. <sect2>Configurando a Política<label id="policy"> <p> Já detalhamos o que acontece quando um pacote chega ao fim de uma cadeia interna quando discutimos como um pacote caminha através das cadeias, anteriormente. Neste caso, a <bf/política/ da cadeia determina o destino do pacote. Somente cadeias internas (<tt/INPUT/, <tt/OUTPUT/ e <tt/FORWARD/) possuem políticas, por que se um pacote chega ao fim de uma cadeia definida pelo usuário, o caminhamento prossegue na cadeia prévia. <p> A política pode ser <tt/ACCEPT/ ou <tt/DROP/, por exemplo: <tscreen><verb> # iptables -P FORWARD DROP # </verb></tscreen> <sect>Usando o ipchains e o ipfwadm<label id="oldstyle"> <p> Existem módulos na distribução do netfilter chamados ipchains.o e ipfwadm.o. Insira um destes em seu kernel (NOTA: eles são incompatíveis com ip_tables.o!). Você pode então usar o ipchains ou o ipfwadm como nos bons e velhos dias. <p> Estas opçõe serão suportadas por algum tempo ainda. Eu penso que uma fórmula razoável é 2 * [notícia da troca - release inicial estável], além da data que um release estável da substitução está disponível. Isto significa que o suporte será descartado provavelmente no Linux 2.6 ou 2.8. <sect>Misturando NAT e Filtro de Pacotes <p> É comum querer fazer Network Address Translation (veja o NAT HOWTO) e filtro de pacotes. As boas novas é ue a mistura funciona muito bem. <p> Você projeta o filtro de pacotes ignorando completamente o NAT que está fazendo. As origens e destinos vistas pelo filtro de pacotes serão as fontes e destinos `reais'. Por exemplo, se você está fazendo que o DNAT para enviar conexões para 1.2.3.4, porta 80, para 10.1.1.1, porta 8080, o filtro de pacotes irá ver pacotes indo para 10.1.1.1, porta 8080 (o destino real), e não 1.2.3.4, porta 80. De forma similar, você pode ignorar o mascaramento. Os pacotes irão parecer estar vindo do endereço IP interno real (digamos 10.1.1.1), e as respostas deverão voltar para lá. <p> Você pode usar a extensão `state' sem fazer que o filtro de pacotes faça nenhum trabalho extra, já que o NAT exige acompanhamento de conexões de qualquer forma. para emlhorar o exemplo simples de mascaramento do NAT HOWTO, para proibir novas conexões vindo da interface ppp0, você faria o seguinte: <tscreen><verb> # Masquerade out ppp0 iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE # disallow NEW and INVALID incoming of forwarded packets from ppp0. iptables -A INPUT -i ppp0 -m state --state NEW,INVALID -j DROP iptables -A FORWARD -i ppp0 -m state --state NEW,INVALID -j DROP # Turn on IP forwarding echo 1 > /proc/sys/net/ipv4/ip_forward </verb></tscreen> <sect>Diferenças Entre o iptables e o ipchains<label id="Appendix-A"> <p> <itemize> <item>Primeiro, os nomes das cadeias internas mudaram de nomes em minúsculas para MAIÚSCULAS, por que as cadeias INPUT e OUTPUT podem agora somente pegar pacotes com destino ou origem loca. Elas vem todos os pacotes que chegam e que saem respectivamente. <item>A flag `-i' agora identifica a interface de entrada, e somente funciona nas cadeias INPUT e FORWARD. As regras nas cadeias FORWARD ou OUTPUT que usavam `-i' devem ser mudadas para `-o'. <item>As portas TCP e UDP precisam ser declaradas com as opções --source-port ou --sport (ou -d-estination-port/dport), e devem ser colcoadas após as opções `-p tcp' ou `-p udp', que carregam as extensões TCP e UDP respectivamente. <item>A flag TCP -y agora é --syn, e deve estar após `-p tcp'. <item>O destino DENY é agora DROP, finalmente. <item>Zerar cadeias ao mesmo tempo que as lista agora funciona. <item>Zerar cadeias internas também limpa os contadores de política. <item>A listagem de cadeis dá os contadores como um snapshot atômico. <item>REJECT e LOG são destinos extendidos, significando que são módulos de kernel separados. <item>Nomes de cadeias podem ter até 31 caracteres. <item>MASQ é agora MASQUERADE e usa uma sintaxe diferente. REDIRECT, em quanto mantém o mesmo nome, também teve uma alteração de sintaxe. Veja o NAT-HOWTO para mais informações sobre como configurar os dois. <item>A opção -o não é mais usada para direcionar pacotes para o dispositivo de userspace (veja o -i acima). Os pacotes são agora enviados ao userspace via o destino QUEUE. <item>Provavelmente cargas de coisas que eu esqueci. </itemize> <sect>Conselhos no Projeto de Filtros de Pacotes <p> É consenso na área de segurança de computadores bloquear tudo, e então abrir os buracos necessários. Isto geralmente é dito como `o que não é explicitamente permitido é proibido'. Eu ercomendo esta abordagem se segurança é sua preocupação maior. <p> Não rode serviços que você não precisa, mesmo que você pensa ter bloqueado o acesso aos mesmos. <p> Se você está criando um firewall dedicado, comece rodando nada, e bloqueando todos os pacotes, e então acrescente serviços e deixe os pacotes irem passando conforme necessário. <p> Eu recomendo segurança em profundidade: combine o tcp-wrappers (para conexões ao próprio filtro de pacotes), proxies (para conexões passando pelo filtro de pacotes), verificação de rota e filtro de pacotes. A verificação de rotas é onde um pacote que vem de uma interface inesperada é descartado: por exemplo, se sua rede interna tem endereços 10.1.1.0/24, e um pacote com aquele endereço de origem vem de sua interface externa, ele será descartado. isto pode ser habilitado para uma interface (ppp0) da seguinte forma: <tscreen><verb> # echo 1 > /proc/sys/net/ipv4/conf/ppp0/rp_filter # </verb></tscreen> Ou para todas as interfaces existentes e futuras assim: <tscreen><verb> # for f in /proc/sys/net/ipv4/conf/*/rp_filter; do # echo 1 > $f # done # </verb></tscreen> O Debian faz isto por padrão onde possível. Se você tem algum roteamento assimétrico (isto é, você espera pacotes vindo de direções estranhas), você vai querer desabilitar este filtro naquelas interfaces. <p> Fazer o log é útil quando estiver configurando um firewall se algo não está funcionando, mas em um firewall de produção, sempre combine isto com a seleção `limit', para evitar que alguém sobrecarregue seus logs. <p> Eu recomendo bastante o uso de acompanhamento de conexões (connection tracking) para sistemas seguros: é acrescentado algum overhead, e todas as conexões são acompanhadas, mas é bastante útil para controlar o acesso à suas redes. Você pode precisar carregar o módulo `ip_conntrack.o' se o seu kernel não carrega módulos automaticamente, e ele não está dentro do kernel. Se você quer acompanhar com precisão protocolos complexos, você vai precisar carregar o módulo apropriado (por exemplo, `ip_conntrack_ftp.o'). <tscreen><verb> # iptables -N no-conns-from-ppp0 # iptables -A no-conns-from-ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT # iptables -A no-conns-from-ppp0 -m state --state NEW -i ! ppp0 -j ACCEPT # iptables -A no-conns-from-ppp0 -i ppp0 -m limit -j LOG --log-prefix "Bad packet from ppp0:" # iptables -A no-conns-from-ppp0 -i ! ppp0 -m limit -j LOG --log-prefix "Bad packet from ppp0:" # iptables -A no-conns-from-ppp0 -j DROP # iptables -A INPUT -j no-conns-from-ppp0 # iptables -A FORWARD -j no-conns-from-ppp0 </verb></tscreen> <p> Montar um bom firewall está além do escopo deste HOWTO, mas meu conselho é `sempre seja minimalista'. Veja o Security HOWTO para mais informações sobre como testar e experimentar seu computador. </article> <!-- vi: set tw=78 ai -->