Página seguinte Página anterior Índice

7. Usando o iptables

O iptables possui uma página de manual bem detalhada (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 Diferenças Entre o iptables e o ipchains; eles são bastante similares.

Existem várias coisas diferenes que você pode fazer com o iptables. Você começa com as três cadeias internas, INPUT, OUTPUT e FORWARD que você não pode apagar. Vamos dar uma olhada nas operações que tratam as cadeias inteiras:

  1. Criar uma nova cadeia (-N).
  2. Apagar uma cadeia vazia (-X).
  3. Mudar a política para uma cadeia interna (-P).
  4. Listar as regras de uma cadeia (-L).
  5. Esvaziar as regras de uma cadeia (-F).
  6. Zerar a contagem de pacotes e de bytes de todas as regras de uma cadeia (-Z).

Existem várias formas de manipular as regras dentro de uma cadeia:

  1. Apensar uma nova regra em uma cadeia (-A).
  2. Inserir uma nova regra em alguma posição da cadeia (-I).
  3. Substituir uma regra em certa posição da cadeia (-R).
  4. Apagar uma regra em uma determinada posição da cadeia (-D).
  5. Apagar a primeira regra que atende a uma pesquisa em uma chain (-D).

7.1 O Que Você Verá Quando Seu Computador Inicializa

O iptables pode ser um módulo, chamado (`iptable_filter.o'), que deve ser carregado automaticamente quando você roda pela primeira vez o comando iptables. Ele também pode ser inserido no kernel permanentemente.

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.

7.2 Operações Em Uma Única Regra

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.

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'.

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.

# 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
#

Pode-se ver que o primeiro ping funciona bem (o `-c 1' informa ao ping para mandar somente um pacote).

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').

Quando testamos nossa regra, usamos o segundo ping. Há uma pausa antes que o programa desista de esperar uma resposta que nunca virá.

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:

# iptables -D INPUT 1
#
Para apagar a regra número 1 na cadeia INPUT.

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:

# iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP
#
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.

7.3 Especificações de Filtro

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.

Especificando Endereços IP de Origem e Destino

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'.

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:

[ NOTA: `-s 0/0' é redundante ]
# iptables -A INPUT -s 0/0 -j DROP
#

Este é raramente usado, já que o efeito é o mesmo de não ter especificado a opção `-s'.

Especificando Inversão

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 não venha de localhost.

Especificando o Protocolo

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'.

O protocolo pode ser prefixado por um `!', para inverter o mesmo, com em `-p ! TCP', para especificar pacotes que não são TCP.

Especificando uma Interface

As opções `-i' (ou `--in-interface') e `-o' (ou `--out-interface') especificam o nome de uma 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).

Pacotes que estejam atravessando a cadeia 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 OUTPUT não tem uma interface de entrada, e qualquer regra que use `-i' nesta cadeia nunca será usada.

Somente pacotes que estão atravessando a cadeia FORWARD possuem tanto a interface de entrada e a de saída.

É 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 é ppp0) e parecidos.

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 -i ppp+ seria usada.

O nome da interface poderia ser precedido por um `!' entre espaço, para combinar com pacotes que não combinem com a interface(s) especificada, como em -i ! ppp+.

Especificando Fragmentos

Algumas vezes um pacote é muito grande para ser colocado de uma vez na rede. Quando isto acontece, o pacote é dividido em fragmentos, e enviado em múltiplos pacotes. A outra ponta remonta estes fragmentos para reconstruir o pacote inteiro.

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.

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.

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 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 -p TCP --sport www (especificando uma porta de origem `www') nunca irá tratar um fragmento (além do primeiro fragmento). Nem a regra oposta -p TCP --sport ! www.

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 não aplique-se ao segundo fragmento e seguintes, precedendo o `-f' com um `!'.

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.

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.

Como um exemplo, o código seguinte irá descartar qualquer fragmento que vá para 192.168.1.1:

# iptables -A OUTPUT -f -d 192.168.1.1 -j DROP
#

Extensões ao iptables: Novas Combinações

O iptables é extensível, o que significa que tanto o kernel e a ferramenta iptables podem ser extendidos para dar novas funcionalidades.

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.

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.

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.

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.

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.

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:

# iptables -p tcp --help
#

Extensões TCP

As extensões TCP são automaticamente carregadas se é especificada `-o tcp'. Elas provêem as seguintes opções (nenhuma das quais para fragmentos):

--tcp-flags

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,

# iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DROP

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.

--syn

Opcionalmente precedida por um `!', é um atalho para `--tcp-flags SYN,RST,ACK SYN'.

--source-port

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 `:'.

--sport

é um sinônimo para `--source-port'.

--destination-port

e

--dport

fazem o mesmo que as opções acima, só que especificam a porta destino, em vez da origem, para combinar.

--tcp-option

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.

Uma Explicação das Flags TCP

À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.

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.

A solução é bloquear somente os pacotes usados para solicitar uma conexão. Estes pacotes são chamados pacotes 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.

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

-p TCP -s 192.168.1.1 --syn

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.

Extensões UDP

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.

Extensões ICMP

Esta extensão é automaticamente carregada se for especificada `-p icmp'. Ela somente suporta uma nova opçõa:

--icmp-type

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'.

Outras Extensões Para Combinar

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'.

mac

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:

--mac-source

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'.

limit

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:

--limit

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').

--limit-burst

seguido por um número, indicando o burst máximo antes que o limite acima é disparado.

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:

# iptables -A FORWARD -m limit -j LOG

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.

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.

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.

Proteção contra syn-flood:

# iptables -A FORWARD -p tcp -sym -m limit --limit 1/s -j ACCEPT

Port-scanner furtivo:

# iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

Ping da Morte:

# iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

Este módulo é como uma "porta de histerese", como mostrado no gráfico abaixo.

       taxa (pkt/s)  
             ^        .---.
             |       / DoS \
             |      /       \
Lim. do DoS -|.....:.........\.......................
 = (limit *  |    /:          \
limit-burst) |   / :           \         .-.
             |  /  :            \       /   \
             | /   :             \     /     \
Fim do DoS  -|/....:..............:.../.......\..../.
 = limit     |     :              :`-'         `--'
-------------+-----+--------------+------------------> tempo(s)
  LOGICA =>  Comb. | Não Combina  |    Combina(Match)

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.


        <--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

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).

owner

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.

--uid-owner userid

Combina se o pacote foi criado por um processo com o id de usuário efetivo (numérico) fornecido.

--gid-owner groupid

Combina se o pacote foi criado por um porcesso com o id de grupo efetivo (numérico) fornecido.

--pid-owner processid

Combina se o pacote foi criado por um processo com o id de processo fornecido.

--sid-owner sessionid

Combina se o pacote foi criado por um proceso no grupo de sessão fornecido.

unclean

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.

A Combinação State

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.

Especificando `-m state', é permitido uma opção adicional `--state', que é uma lista separada por vírgulas dos estados a selecionar (a flag `!' indica que não devem ser selecionados aqueles estados). Os estados são:

NEW

Um pacote que cria uma nova conexão.

ESTABLISHED

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).

RELATED

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.

INVALID

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.

7.4 Especificação de Destino

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 destino (target) da regra.

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.

Existem dois tipos de destinos além dos internos: extensões e cadeias definidas pelo usuário.

Cadeias Definidas pelo Usuário

Uma funcionalidade poderosa que o iptables herda do 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 Operações em Cadeias Inteiras).

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.

Hora de uma ASCII art. Considere duas cadeias (bobas): INPUT (a cadeia interna) e test (uma cadeia definida pelo usuário).

         `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    |
        ----------------------------

Considere um pacote TCP vindo de 192.168.1.1, indo para 1.2.3.4. Ele entra na cadeia INPUT, e é testado contra a regra Rule1 - não é selecionado. A Rule2 combina, e seu destino é test, então a próxima regra a ser examinada é o início de test. A regra Rule1 em 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 INPUT, onde acabamos de examinar a regra Rule2, então iremos examinar a regra Rule3, que também não combina.

Assim, o caminho percorrido pelo pacote é:

                                v    __________________________
         `INPUT'                |   /    `test'                v
        ------------------------|--/    -----------------------|----
        | Rule1                 | /|    | Rule1                |   |
        |-----------------------|/-|    |----------------------|---|
        | Rule2                 /  |    | Rule2                |   |
        |--------------------------|    -----------------------v----
        | Rule3                 /--+___________________________/
        ------------------------|---
                                v

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).

Extensões ao iptables: Novos Destinos

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 iptables para fornecer novas opções de linha de comando. Existem várias extensões na distribução padrão do netfilter:

LOG

Este módulo faz o log a nível de kernel dos pacotes que forem selecionados. Ela permite as seguintes opções adicionais:

--log-level

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.

--log-prefix

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.

Este módulo é mais útil após uma seleção de limite, de forma a não sobrecarregar os logs.

REJECT

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):

O REJECT também aceita um argumento opcional `--reject-with' que altera o pacote de resposta usado: veja a página de manual.

Destinos Internos Especiais

Existem dois destinos internos especiais: RETURN e QUEUE.

O 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.

O 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;

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.

A seguir há um rápido exemplo de como usar o iptables para enfileirar pacotes para processamento no userspace:

# modprobe iptable_filter
# modprobe ip_queue
# iptables -A OUTPUT -p icmp -j QUEUE
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.

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.

O status de ip_queue pode ser verificado via:

/proc/net/ip_queue
O comprimento máximo da fila (ou seja, o número de pacotes despachados para o userspace sem veredito devolvido) pode ser controlado via:
/proc/sys/net/ipv4/ip_queue_maxlen
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.

7.5 Operações em Cadeias Inteiras

Uma funcionalidade bastante útil do 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.

Criando uma Nova Cadeia

Vamos criar uma nova cadeia. Como eu sou uma pessoa bastante criativa, eu vou chamar ela de test. usamos a opção `-N' ou `--new-chain':

# iptables -N test
#

É assim simples. Agora você pode inserir regras como foi mostrado acima.

Apagando uma Cadeia

Apagar uma cadeia é simples também, usando as opções `-X' ou `--delete-chain'. Por quê `-X'? Todas as letras legais já foram usadas.

# iptables -X test
#

Existe um par de restrições para apagar uma cadeia: elas devem estar vazias (veja 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.

Se você não especificar uma cadeia, então todas as cadeias definidas pelo usuário serão apagadas, se possível.

Esvaziando uma Cadeia

Existe uma forma simples de esvaziar todas as regras de uma cadeia, usando o comando `-F' (ou `--flush').

# iptables -F FORWARD
#

Se você não especificar uma cadeia, então todas as cadeias serão esvaziadas.

Listando uma Cadeia

Você pode listar todas as regras em uma cadeia usando o comando `-L' (ou `--list').

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.

Se o nome da cadeia é omitido, todas as cadeias são listadas, mesmo as vazias.

Aqui estão três opções que podem acompanhar o `-L'. A opção `-n' (numérica) é bastante útil por evitar que o 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.

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.

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.

Reinicializando (Zerando) Contadores

É útil poder reiniciar os contadores. Isto pode ser feito com a opção `-Z' (ou `--zero').

Considere o seguinte:

# iptables -L FORWARD
# iptables -Z FORWARD
#

No exemplo acima, alguns pacotes podem passar entre os comandos `-L' e `-Z'. Por esta razão, você pode usar o `-L' e `-Z' juntos, para reiniciar os contadores ao mesmo tempo que lê os mesmos.

Configurando a Política

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 política da cadeia determina o destino do pacote. Somente cadeias internas (INPUT, OUTPUT e 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.

A política pode ser ACCEPT ou DROP, por exemplo:

# iptables -P FORWARD DROP
#


Página seguinte Página anterior Índice 1