Página seguinte Página anterior Índice

7. Utilizando o iptables

O iptables tem uma página de manual muito detalhada (man iptables), se você necessitar de informações mais específicas. Aqueles mais familiarizados com o ipchains provavelmente gostarão de ler Diferenças entre iptables e ipchains; eles são bem similares.

Há muitas coisas que podem ser feitas com iptables. Você começa com três chains built-in INPUT, OUTPUT e FORWARD as quais não podem ser apagadas. Estas são as operações para gerenciar chains:

  1. Criar nova chain (-N).
  2. Apagar uma chain vazia (-X).
  3. Mudar a política de uma chain built-in. (-P).
  4. Listar as regras de uma chain (-L).
  5. Apagar todas as regras de uma chain (-F).
  6. Zerar os contadores de pacotes e bytes de todas as regras de uma chain (-Z).

Há várias formas de manipular regras dentro de uma chain:

  1. Adicionar uma nova regra na chain (-A).
  2. Inserir uma nova regra em alguma posição da chain (-I).
  3. Substituir uma regra em alguma posição da chain (-R).
  4. Apagar uma regra em alguma posição da chain (-D).
  5. Apagar a primeira regra que associa (com alguma condição) numa chain (-D).

7.1 O que será visto quando seu computador iniciar

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

Antes dos comandos do iptables rodarem (cuidado: algumas distribuições rodarão iptables em seus scripts de inicialização), não haverão regras em quaisquer chains (`INPUT', `FORWARD' and `OUTPUT') e todas as chains terão a política ACCEPT. A política padrão da chain FORWARD pode ser alterada fornecendo o parâmetro `forward=0' para o módulo iptable_filter.

7.2 Operações em uma única regra

Este é o arroz com feijão da filtragem de pacotes: manipular regras. Usualmente, você provavelmente utilizará os comandos para adicionar (-A) e apagar (-D). Os outros (-I para inserir e -R para substituir) são apenas extensões destes conceitos.

Cada regra especifica uma série de condições que o pacote deve atender, e o que fazer com o mesmo se ele atendê-las (um alvo `target'). Por exemplo, você pode desejar descartar todos os pacotes ICMP vindos do endereço IP 127.0.0.1. Então neste caso nossas condições são que o protocolo precisa ser ICMP e o endereço de origem deve ser 127.0.0.1. Nosso alvo (target) é `DROP'.

127.0.0.1 é a interface `loopback', que existirá mesmo que você não tenha nenhuma conexão de rede real. Pode-se utilizar o programa `ping' para gerar esse tipo de pacote (ele simplesmente manda um ICMP tipo 8 (requisição de eco) que é respondido pelos hosts com um ICMP tipo 0 (resposta de eco)).

# 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 é bem sucedido (a opção `-c 1' diz ao ping para mandar um único pacote).

Então foi adicionada (-A) à chain `INPUT', uma regra especificando que pacotes vindos de 127.0.0.1 (`-s 127.0.0.1') com o protocolo ICMP (`-p icmp') devem ser mandados para DROP (`-j DROP').

Logo depois, testamos nossa regra, usando um segundo ping. Haverá uma pausa antes que o programa desista de esperar pelo pacote que nunca viria.

Pode-se apagar regras de duas maneiras. Primeiramente, desde que sabemos que existe apenas uma regra na chain INPUT, podemos utilizar um número para designar a regra, como abaixo:

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

A segunda forma, é fazer o mesmo que faríamos para adicionar a regra, trocando -A por -D. Isso é útil quando você tem uma chain muito complexa e não quer contar para descobrir que a regra 37 deve ser apagada. Neste caso usaria-se:

        # iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP
        #
A sintaxe do -D deve ter exatamente as mesmas opções que seriam passadas para a opção -A (ou -I ou -R). Se existem várias regras idênticas na mesma chain, apenas a primeira será apagada.

7.3 Especificações para filtragem

Foi visto o uso do `-p' para especificar o protocolo, e `-s' para especificar o endereço de origem, mas existem outras opções que podem ser utilizadas para especificar outras características dos pacotes. O que segue é uma explicação exaustiva.

Especificando endreços IP de origem e destino

Endereços IP de Origem (`-s', `--source' or `--src') e destino (`-d', `--destination' or `--dst') podem ser especificados em quatro formas diferentes. A mais comum é utilizar o nome completo, como `localhost' ou `www.linuxhq.com'. A segunda é dizer o IP, como `127.0.0.1'.

A terceira e a quarta formas permitem a especificação de um grupo de endereços IP, como `199.95.207.0/24' ou `199.95.207.0/255.255.255.0'. Ambas especificam qualquer endereço IP de 199.95.207.0 até 199.95.207.255; os dígitos depois da `/' dizem quais partes do endereço IP são significantes. `/32' ou `/255.255.255.255' é o padrão (associando o endereço IP inteiro). Para especificar qualquer endereço IP pode-se utilizar `/0', conforme descrito abaixo:

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

Isso raramente é utilizado, uma vez que o efeito da regra acima é o mesmo que se não fosse especificada nenhuma origem.

Especificando Inversão

Muitas flags, incluindo `-s' (or `--source') e `-d' (`--destination') podem ter seus argumentos precedidos de `!' (pronunciado `não') para associar-se com endereços DIFERENTES aos passados à opção. Por exemplo, '-s ! localhost' associa-se com qualquer pacote que não venha de localhost.

Especificando protocolo

O protocolo pode ser especificado com `-p' (ou `--protocol'). O protocolo pode ser um número (se você sabe o valor numérico dos protocolos) ou um nome para casos especiais como `TCP', `UDP' or `ICMP'. Digitar em maiúsculas ou minúsculas não faz diferença, `tcp' funciona tão bem como `TCP'.

Se o nome do protocolo é precedido de `!', a fim de invertê-lo, como `-p! TCP', a regra especificará todos os pactoes que não são TCP.

Especificando uma interface

As opções `-i' (or `--in-interface') e `-o' (or `--out-interface') especificam o nome de uma interface a especificar. Uma interface é um dispositivo físico pelo qual o pacote veio (`-i') ou está saindo (`-o'). Pode-se usar o comando ifconfig para listar as interfaces ativas.

Pacotes atravessando a chain INPUT não possuem interface de saída, logo qualquer regra utilizando `-o' nessa chain nunca aplicar-se-á. Da mesma forma, pacotes atravessando a chain OUTPUT não têm interface de entrada, logo qualquer regra utilizando `-i' nessa chain nunca aplicar-se-á.

Apenas pacotes passando pela chain FORWARD têm interfaces de entrada e saída.

Não há nenhum problema em especificar uma interface que ainda não existe; a regra não associar-se-á com quaisquer pacotes até que a interface torne-se ativa. Isso é extremamente útil para links discados PPP (usualmente com a interface ppp0) e similares.

Como um caso especial, um nome de interface terminando com um `+' vai associar-se com todas as interfaces (existam elas ou não) que comecem com aquela string. Por exemplo, para especificar uma regra que se associa com todas as interfaces PPP, a opção -i ppp+ deve ser criada.

O nome da interface pode ser precedido de `!' para se associar com um pacote que não é representado pelas interface(s) especificada(s).

Especificando fragmentos

Às vezes um pacote é muito grande para ser enviado todo de uma vez. Quando isso ocorre, o pacote é dividido em fragmentos, e é enviado como múltiplos pacotes. Quem o recebe, remonta os fragmentos reconstruindo o pacote.

O problema com os fragmentos é que o fragmento incial tem os campos de cabeçalho completos (IP + TCP, UDP e ICMP) para examinar, mas os pacotes subsequentes só têm um pequeno grupo de cabeçalhos (somente IP, sem os campos dos outros protocolos). Logo examinar o interior dos fragmentos subsequentes em busca de cabeçalhos de outros protocolos (como extensões de TCP, UDP e ICMP) é impossível.

Se você está fazendo acompanhamento de conexões ou NAT, todos os fragmentos serão remontados antes de atingirem o código do filtro de pacotes, então você não precisa se preocupar sobre os fragmentos.

Caso contrário, é importante entender como os fragmentos são tratados pelas regras de filtragem. Qualquer regra de filtragem que requisitar informações que não existem não será válida. Isso significa que o primeiro fragmento é tratado como um pacote qualquer. O segundo e os seguintes não serão. Então uma regra -p TCP --sport www (especificando 'www' como porta de origem) nunca se associar-se-á com um fragmento (exceto o primeiro). O mesmo se aplica à regra oposta -p TCP --sport ! www.

De qualquer forma, você pode especificar uma regra especial para o segundo e os fragmentos que o sucedem, utilizando a flag `-f' (ou `--fragment'). Também é interessante especificar uma regra que não se aplica ao segundo e os outros fragmentos, precedendo a opção `-f' com `!'.

Geralmente é reconhecido como seguro deixar o segundo fragmento e os seguintes passarem, uma vez que o primeiro fragmento será filtrado, logo isso vai evitar que o pacote todo seja remontado na máquina destinatária. De qualquer forma, há bugs que levam à derrubada de uma máquina através do envio de fragmentos. A decisão é sua.

Nota para os administradores de rede: pacotes mal formados (pacotes TCP, UDP e ICMP muito pequenos para que o código do firewall possa ler as portas ou o código e tipo dos pacotes ICMP) são descartados quando ocorrem tais análises. Então os fragmentos TCP começam na posição 8.

Como um exemplo, a regra a seguir vai descartar quaisquer fragmentos destinados ao endereço 192.168.1.1:

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

Extensões ao iptables: Novas Implementações

O iptables é extensível, assim, tanto o kernel quanto o iptables podem ser extendidos para fornecer novas funcionalidades.

Algumas dessas extensões são padronizadas, e outras são mais exóticas. Extensões podem ser feitas por qualquer um e distribuídas separadamente para usuários de nichos mais específicos.

As extensões do kernel geralmente estão no subdiretório de módulos do kernel como, por exemplo, /lib/modules/2.3.15/net. Elas são carregadas por demanda se seu kernel foi compilado com a opção CONFIG_KMOD marcada, não havendo a necessidade de inserí-las manualmente.

As extensões do iptables são bibliotecas compartilhadas as quais geralmente estão em /usr/local/lib/iptables/, mas uma distribuição os colocaria em /lib/iptables ou /usr/lib/iptables.

Extensões vêm em dois tipos diferentes: novos alvos (targets), e novas associações (depois falaremos mais sobre novos alvos 'targets'). Alguns protocolos automaticamente oferecem novos testes: atualmente são eles TCP, UDP e ICMP como mostrado abaixo.

Para esses protocolos você poderá especificar novos testes na linha de comando depois da opção `-p', que carregará a extensão. Para novos testes explícitos, utilize a opção `-m' para carregar a extensão, depois de -m, todas as opções da extensão estarão disponíveis.

Para conseguir ajuda com uma extensão, utilize a opção que a carrega (`-p', `-j' ou `-m') sucedida por `-h' ou `--help', conforme o exemplo:

# iptables -p tcp --help
#

Extensões TCP

As extensões TCP são automaticamente carregadas se é especificada a opção `-p tcp'. Elas provêm as seguintes opções (nenhuma associa-se com fragmentos).

--tcp-flags

seguida por uma opcional `!', e por duas strings indicando flags, permite que sejam filtradas flags TCP específicas. A primeira string de flags é a máscara: uma lista de flags que serão examinadas. A segunda string diz quais flags devem estar ativas para que a regra se aplique. Por exemplo:

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

Essa regra indica que todas as flags devem ser examinadas (`ALL' é sinônimo de `SYN,ACK,FIN,RST,URG,PSH'), mas apenas SYN e ACK devem estar ativadas. Também há um argumento `NONE' que significa nenhuma flag.

--syn

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

--source-port

seguido por `!' opcional, e uma única porta TCP, ou um conjunto (range) de portas. As portas podem ser descritas pelo nome, conforme listado em /etc/services, ou pelo número. Conjuntos (ranges) são dois nomes de portas separados por `:', ou (para especificar uma porta maior ou igual à especificada) uma porta sucedida por `:', ou (para especificar uma porta menor ou igual à especificada), uma porta precedida por `:'.

--sport

é sinônimo de `--source-port'.

--destination-port

e

--dport

funcionam de forma idêntica a

--source-port

, a única diferença é que elas indicam a porta de destino, e não a porta de origem.

--tcp-option

seguida por `!' opcional e um número, associa-se com um pacote com a opção TCP igual ao do número passado. Um pacote que não tem um cabeçalho TCP completo é automaticamente descartado se há uma tentativa de examinar suas opções TCP.

Uma explicação sobre as flags TCP

Às vezes é util permitir conexões TCP em uma única direção, mas não nas duas. Por exemplo, você permitirá conexões em um servidor WWW externo, mas não conexões vindas deste servidor.

Uma tentativa ingênua seria bloquear pacotes TCP vindos do servidor. Infelizmente, conexões TCP necessitam de pacotes bidirecionais para um funcionamento perfeito.

A solução é bloquear apenas os pacotes utilizados para requisitar uma conexão. Tais pacotes são chamados pacotes SYN (ok, tecnicamente eles são pacotes com a flag SYN marcada, e as flags RST e ACK desmarcadas, mas dizemos pacotes SYN como atalho). Ao não permitir tais pacotes, nós impedimos conexões vindas do servidor.

A opção `--syn' é utilizada para isso: só é válida para regras que especificam TCP como protocolo. Por exemplo, para especificar conexões TCP vindas do endereço 192.168.1.1:

-p TCP -s 192.168.1.1 --syn

Essa opção pode ser invertida se precedida por `!', o que significa qualquer pacote exceto os que iniciam conexões.

Extensões UDP

Essas extensões são automaticamente carregadas se a opção `-p udp' é especificada. Ela provê as opções `--source-port', `--sport', `--destination-port' and `--dport' conforme detalhado para o TCP acima.

Extensões ICMP

Essas extensões são automaticamente carregadas se a opção `-p icmp' é especificada. Ela só possui uma opção diferente das demais:

--icmp-type

seguida por `!' opcional, e um nome de tipo icmp (por exemplo, `host-unreachable'), ou um tipo numérico (exemplo `3'), ou um tipo numérico e código separados por `/' (exemplo `3/3'). Uma lista de tipos icmp é passada utilizando-se `-p icmp --help'.

Outras extensões

Outras extensões no pacote netfilter são extensões de demonstração, que (caso instaladas) podem ser chamadas com a opção `-m'.

mac

Este módulo deve ser explicitamente especificado com `-m mac' ou `--match mac'. Ele é usado para associar-se com o endereço Ethernet (MAC) de origem do pacote, e logo só é útil nas chains PREROUTING e INPUT. Só provê uma única opção:

--mac-source

seguida por `!' opcional e um endereço ethernet passado em notação hexa, exemplo `--mac-source 00:60:08:91:CC:B7'.

limit

Este módulo deve ser explicitamente especificado com `-m limit' ou `--match limit'. É usado para restringir a taxa de pacotes, e para suprimir mensagens de log. Vai fazer com que a regra seja válida apenas um número de vezes por segundo (por padrão 3 vezes por hora, com um limite máximo def 5). Possui dois argumentos opcionais:

--limit

seguido de um número; especifica a média máxima de pacotes (ou LOGs, etc) permitida por segundo. Pode-se especificar a unidade de tempo, usando `/second', `/minute', `/hour' ou `/day', ou abreviações dos mesmos (assim, `5/second' é o mesmo que `5/s').

--limit-burst

seguido de um número, indicando o máximo de entradas antes do limite tornar-se válido.

Essa extensão pode ser usada com o alvo (target) LOG para criar registros (logs) limitados por taxa de incidência. Para entender o funcionamento disso, olhe a regra abaixo, que loga pacotes com os parâmetros padrão de limite:

# iptables -A FORWARD -m limit -j LOG

Na primeira vez que essa regra é analizada, o pacote será logado; na realidade, uma vez que o padrão máximo é 5, os cinco primeiros pacotes serão logados. Depois disso, passar-se-ão vinte minutos antes de que essa regra faça um novo logo, independente do número de pacotes que entrarem. Além disso, a cada vinte minutos que se passam sem que um pacote associe-se com a regra, o contador é diminuido em uma unidade. Logo, se nenhum pacote associar-se com a regra em 100 minutos, o limite estará zerado, voltando ao estágio inicial.

Nota: não é possível criar uma regra com tempo de recarga superior a 59 horas, então se você configura uma taxa média de um por dia, seu limite máximo deve ser menor que 3.

Esse módulo também pode ser usado para evitar uma série de ataques do tipo negativa de serviço (denial of service 'DoS') com uma taxa mais rápida, a fim de aumentar a sensibilidade do sistema.

Proteção contra Syn-flood:

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

Port scanner suspeito:

# 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

Esse módulo funciona como uma "porta com resposta retardada", conforme o gráfico abaixo.

       taxa (pkt/s)  
             ^        .---.
             |       / DoS \
             |      /       \
Auge do DoS -|.....:.........\.......................
 = (média *  |    /:          \
média-máxim) |   / :           \         .-.
             |  /  :            \       /   \
             | /   :             \     /     \
Fim do DoS  -|/....:..............:.../.......\..../.
 = média     |     :              :`-'         `--'
-------------+-----+--------------+------------------> time (s)
  LOGICA =>  Passa |  Não passa   |    Passa

Digamos que aprovamos um pacote por segundo com um limite máximo de cinco pacotes, mas os pacotes começam a vir quatro por segundo, durante três segundos, e recomeçam depois de mais 3 segundos.



        <--Flood 1-->           <---Flood 2--->

Total  ^                   Line  __--      YNNN
de     |               Rate  __--      YNNN
Pacotes|            mum  __--      YNNN
    10 |        Maxi __--         Y
       |         __--            Y
       |     __--               Y
       | __--    YNNN           
       |-    YNNN
     5 |    Y    
       |   Y                            Legenda:  Y -> Regra válida
       |  Y                                       N -> Regra deixou de valer
       | Y
       |Y 
     0 +-------------------------------------------------->  Time (seconds)
        0   1   2   3   4   5   6   7   8   9  10  11  12

Nota de Tradução: Desculpem-me, mas eu não consegui traduzir esse gráfico sem
deformá-lo completamente, então algumas coisas ficaram em inglês :)

Percebe-se que os cinco primeiros pacotes podem exceder um pacote por segudo, depois o limite máximo passa a ser válido. Se há uma nova tentativa de flood, os pacotes são aceitos, mas apenas no limite estabelecido pela regra (1 pacote por segundo pois a cota do limite máximo já foi gasta).

owner

Esse módulo tenta associar-se com várias características do criador do pacote, para pacotes gerados localmente. Só é válido na chain OUTPUT, e mesmo assim alguns pacotes (como respostas de ping ICMP) podem nao ter dono, e nunca serão analizados pela regra.

--uid-owner userid

Associa-se com o pacote se este foi criado por um processo com o userid igual ao passado na opção.

--gid-owner groupid

Associa-se com o pacote se este foi criado por um processo com o groupid igual ao passado na opção.

--pid-owner processid

Associa-se com o pacote se este foi criado por um processo com o proccessid igual ao passado na opção.

--sid-owner sessionid

Associa-se com o pacote se este foi criado por um processo com o sessionid igual ao passado na opção.

unclean

Esse módulo experimental deve ser explicitamente especificado com `-m unclean' ou `--match unclean'. Ele faz diversas checagens de sanidade nos pacotes. Esse módulo não foi auditado, e não deve ser utilizado como dispositivo de segurança (ele provavelmente torna as coisas piores, uma vez que provavelemente está cheio de bugs). Não possui opções

Checagens de estado dos pacotes (state match)

O critério para filtragem de pacotes mais útil é provido pela extensão 'state' que interpreta a análise do controle da conexão feita pelo módulo `ip_conntrack'. Essa extensão é altamente recomendada.

Especificando `-m state' a opção `--state' torna-se disponível, a qual é uma lista dos estados possíveis dos pacotes separada por vírgula (a opção `!' indica para que a regra não se associe com os estados passados). 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, um pacote saindo por uma conexão na qual já houveram respostas).

RELATED

Um pacote relacionado, mas que não faz parte, de uma conexão existente, como um erro ICMP, ou (com o módulo FTP carregado), um pacote estabelecendo uma conexão de dados FTP.

INVALID

Um pacote que não pôde ser identificado por alguma razão: isso inclui falta de memória e erros ICMP que não correspondem a qualquer conexão conhecida. Geralmente tais pacotes devem ser descartados.

7.4 Especificações de alvo (Target)

Agora que sabemos quais as análises podem ser feitas em um pacotes, precisamos de uma forma de dizer o que fazer com os pacotes que passam nas condições que estabelecemos. Isso é chamado de alvo (target) da regra.

Há dois alvos bem simples: DROP (descartar) e ACCEPT (aceitar). Nós já os vimos. Se a regra se associa com o pacote e seu alvo é um desses dois, nenhuma outra regra é consultada: o destino do pacote já foi decidido.

Há dois tipos de alvos diferentes dos descritos acima: as extensões e as chains definidas por usuários.

Chains definidas por usuários

Uma funcionalidade que o iptables herdou do ipchains é a possibilidade do usuário criar novas chains, além das três padrão (INPUT, FORWARD e OUTPUT). Por convenção, chains definidas pelo usuário são escritas em minúsculas, diferenciando-as (como criar chains definidas pelo usuário será descrito abaixo Operações em uma chain).

Quando um pacote associa-se com uma regra cujo alvo (target) é uma chain definida pelo usuário, o pacote passa a ser analizado pelas regras dessa chain definida pelo usuário. Se a chain não decide o que deve ser feito com o pacote, o mesmo volta a ser analizado pela chain padrão que continha a regra que o levava para a chain definida pelo usuário.

Mais arte ASCII. Considere duas chains: INPUT (a chain padrão) e test (uma chain definida pelo usuário).

         `INPUT'                         `test'
        ----------------------------    ----------------------------
        | Regra1: -p ICMP -j DROP  |    | Regra1: -s 192.168.1.1   |
        |--------------------------|    |--------------------------|
        | Regra2: -p TCP -j test   |    | Regra2: -d 192.168.1.1   |
        |--------------------------|    ----------------------------
        | Regra3: -p UDP -j DROP   |
        ----------------------------

Considere um pacote TCP vindo de 192.168.1.1, indo para 1.2.3.4. Ele entra na chain INPUT e é testado pela Regra1 - não se associa. Já a Regra2 se associa, e seu alvo é test, logo a próxima regra examinada está no início de test. A Regra1 na chain test se associa, mas não especifica um alvo, então a próxima regra é examinada, Regra2. Ela não se associa, e nós chegamos no final da chain. Então, a chain INPUT volta a ser examinada, e como a úlitma regra desta chain que foi examinada foi a Regra2, a regra a ser examinada agora é a Regra3, que também não se associa com o pacote.

Logo, o caminho que o pacote faz é o seguinte:

                                v    __________________________
         `INPUT'                |   /    `test'                v
        ------------------------|--/    -----------------------|----
        | Regra1                | /|    | Regra1               |   |
        |-----------------------|/-|    |----------------------|---|
        | Regra2                /  |    | Regra2               |   |
        |--------------------------|    -----------------------v----
        | Regra3                /--+___________________________/
        ------------------------|---
                                v

Chains definidas por usuário podem ter como alvo outras chains definidas por usuário (mas não faça loops: seus pacotes serão descartados se entrarem em loop).

Extensões ao iptables: Novos alvos (targets).

O outro tipo de alvo é uma extensão. Uma extensão-alvo consiste em um módulo do kernel, e uma extensão opcional ao iptables para prover opções de linha de comando. Há diversas extensões na distribuição padrão do netfilter:

LOG

Esse módulo provê logging dos pacotes submetidos. Possui as seguintes opçoes adicionais: packets. It provides these additional options:

--log-level

Seguido de um número de nível ou nome. Os nome válidos (sensíveis a maiúsculas/minúsculas) são `debug', `info', `notice', `warning', `err', `crit', `alert' and `emerg', correspondendo a números de 7 até 0. Veja a página de manual do syslog.conf para uma explicaçao mais detalhada desses níveis.

--log-prefix

Seguido de uma string de até 29 characters, esta será adicionada no início da mensagem de log, permitindo melhor identificação da mesma.

Esse módulo é últil após de uma comparação por limite (limit match), assim, você não enche seus logs.

REJECT

Esse módulo tem o mesmo efeito de `DROP', a não ser que o remetente tenha enviado uma mensagem de erro ICMP `port unreachable' (porta inalcançável) A mensagem de erro ICMP não será enviada se (veja RFC 1122):

REJECT também tem o argumento opcional '-reject-with' que altera o pacote de resposta utilizado: veja a página de manual.

Alvos especiais padrão

Há dois tipos especiais de alvos padrão: RETURN e QUEUE.

RETURN tem o mesmo efeito de chegar ao final da chain: para uma regra numa chain padrão, a política da chain é executada. Para uma chain definida por usuário, a travessia continua na chain anterior, exatamente após a regra que saltou para a chain definida pelo usuário.

QUEUE é um alvo especial, que manda o pacote para uma fila para processamento em nível de usuário. Para isso ser útil, dois componentes são necessários:

O gerenciador de filas padrão para o iptables IPv4 iptables é o módulo ip_queue, que é distribuído com o kernel e é atualmente experimental.

O seguinte é um rápido exemplo de como utilizar o iptables para enfileirar pacotes para processamento em nível de usuário:

# modprobe iptable_filter
# modprobe ip_queue
# iptables -A OUTPUT -p icmp -j QUEUE
Com essa regra, pacotes ICMP de saída gerados localmente (como, por exemplo, criados pelo ping) são passados ao módulo ip_queue, que então tenta mandar os pacotes para uma aplicação em nível de usuário. Se não há nenhuma aplicação em nível de usuário está esperando, os pacotes são descartados.

Para escrever uma aplicação em nível de usuário, utilize a API libipq, que é distribuída com o iptables. Códigos de exemplo podem ser encontradas com as ferramentas testsuite (por exemplo redirect.c) no CVS.

O estado de ip_queue pode ser consultado através de:

/proc/net/ip_queue
O comprimento máximo da fila (exemplo, o número de pacotes entregues ao espaço do usuário sem que nenhuma resposta fosse passada) pode ser controlado por:
/proc/sys/net/ipv4/ip_queue_maxlen
O valor padrão para o comprimento máximo da fila é 1024. Uma vez que esse limite foi atingido, novos pacotes serão descartados até que o tamanho da fila diminua abaixo do limite. Bons protocolos como o TCP interpretam pacotes descartados como congestionamento, que talvez voltem quando a fila diminua. De qualquer forma, experimentos para determinar o tamanho ideal da fila pois às vezes o tamanho padrão é muito pequeno.

7.5 Operações em uma chain

Uma funcionalidade muito importante do iptables é a habilidade de ajuntar regras em chains (cadeias). Você pode dar o nome que quiser para as chains, mas é recomendada a utilização de minúsculas para evitar confusão com as chains padrão ou com os alvos (targets). Nomes de chains podem ter até 31 letras.

Criando uma nova chain

Criemos uma nova chain. Devido à minha imensa criatividade, vou chamá-la de test. Utiliza-se as opções `-N' ou `--new-chain':

# iptables -N test
#

É tão simples assim. Agora é possível acrescentar regras conforme descrito em todo o documento.

Apagando uma Chain

Apagar uma chain é tão simples quanto criá-la, utilizando as opções `-X' ou `--delete-chain'. Porque `-X'? Bem, todas as boas letras já haviam sido utilizadas.

# iptables -X test
#

Há uma série de restrições ao se apagar uma chain: ela deve estar vazia (veja Esvaziando uma chain, logo abaixo) e ela não deve ser alvo de NENHUMA regra. É impossível apagar nenhuma das três chains padrão.

Se uma chain não for especificada, todas as chains definidas por usuário serão apagadas, desde que seja possível.

Esvaziando uma chain

Há uma forma muito simples de retirar todas as regras de uma chain, utilizando as opções `-F' (ou `--flush').

# iptables -F FORWARD
#

Se uma chain nao for especificada, todas as chains serão esvaziadas.

Listando uma chain

Pode-se listar todas as regras de uma chain utilizando as opções `-L' (ou `--list')

O valor `refcnt' listado para cada chain definida por usuário é o número de regras que têm tal chain como alvo (target). Este valor deve ser zero (e a chain deve estar vazia) antes que essa chain possa ser apagada.

Se o nome da chain é omitido, todas as chains são listadas, até as vazias.

Há três opçoes que podem acompanhar `-L'. A opção `-n' (numérico) é muito útil uma vez que previne que o iptables tente resolver os endereços IP, o que (se você utiliza DNS assim como a maioria das pessoas) causaria grandes atrasos se o DNS não está configurado corretamente, ou você está filtrando requisições DNS. Essa opção também faz as portas TCP e UDP serem impressas como números em vez de nomes.

A opção `-v' mostra todos os detalhes das regras, como os contadores de pacotes e bytes, as comparações TOS, e as interfaces. Caso tal opção não seja passada, esses valores sao omitidos.

Note que os contadores de pacotes e bytes são impressos com os sufixos `K', `M' ou `G' para 1.000, 1.000.000 e 1.000.000.000 respectivamente. Utilizando a flag `-x' (expandir números) os números serão impressos inteiros, independente de seu tamanho.

Zerando contadores

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

Considere o seguinte:

# iptables -L FORWARD
# iptables -Z FORWARD
# 

No exemplo acima, alguns pacotes passariam pelos comandos `-L' e `-Z'. Por isso, você pode utilizar `-L' e `-Z' em conjunto, para zerar os contadores enquantos estes são lidos.

Escolhendo política

Já discutimos sobre o que ocorre quando um pacote chega ao fim de uma chain padrão quando o caminho dos pacotes através das chains. Nesse caso, a política da chain determina o destino do pacote. Apenas as chains padrão (INPUT, OUTPUT e FORWARD) têm políticas, porque se um pacote chega ao fim de uma chain definida por usuário, o caminho do pacote continua pela chain anterior.

A política pode ser tanto ACCEPT (aceitar) quanto DROP (rejeitar), por exemplo:

# iptables -P FORWARD DROP
#


Página seguinte Página anterior Índice