Filtrando Pacotes com Iptables

Transcrição

Filtrando Pacotes com Iptables
Usando Kernel 2.4 + Netfilter/Iptables
Parte 1 : Filtrando Pacotes
por Ricardo Kléber <[email protected]>
Entendendo Filtro de Pacotes
Filtro de pacotes é um tipo (arquitetura) de firewalls onde dados (pacotes IP) chegam até ele, que - baseado na
leitura dos cabeçalhos dos pacotes - decide se os passa (ACCEPT) ou não (DROP/REJECT) para a rede,
dependendo de regras de filtragem embutidas em seu sistema operacional (kernel). É uma arquitetura
considerada rápida e flexível.
No Linux, a filtragem de pacotes é feita no kernel (como um módulo ou compilado diretamente nele). Existem
algumas funções de manipulação de pacotes, porém, essencialmente esse módulo lê os cabeçalhos dos pacotes
e decide o que fazer com ele.
Utilização da Filtragem de Pacotes
Controle:
Quando utilizamos um Sistema Linux para conectar uma rede interna a outra rede (especificamente à
Internet), podemos permitir certos tipos de tráfego e proibir outros.
Por exemplo, o cabeçalho de um pacote contém um endereço de destino, o qual podemos barrar, se
estes pacotes estiverem vindo de certos locais de fora da rede interna que não queremos que atinjam
este endereço de destino. Outro exemplo seria, ao utilizarmos um browser (como o Netscape), e
acessarmos um site que nos impele a clicar em um botão para receber algo. As regras de filtragem
podem barrar o conteúdo vindo de determinada origem duvidosa.
Segurança:
Quando o seu Sistema Linux estiver conectado ao "caos" da Internet, a filtragem de pacotes pode
restringir a utilização indevida de portas de sua máquina. Técnicas de ataque utilizadas por pessoas
contra a sua máquina, como o "Ping da Morte" que deixam sua máquina lenta ou simplesmente
impossibilitam a sua utilização momentaneamente, podem ser evitados com a filtragem. Você também
pode bloquear o acesso externo à sua máquina, evitando a manipulação por pessoas não autorizadas
de seus arquivos e senhas. Talvez você deseje (como a maioria das pessoas) ser um observador da
Internet, e não prover serviços (como servidores de home pages, ftp, etc.). Simplesmente não permita
que ninguém acesse sua máquina externamente, fazendo com que o seu filtro de pacotes rejeite todos
os pacotes que solicitem conexões em sua máquina.
Vigilância:
Algumas vezes uma máquina mal configurada em uma rede local passa a enviar pacotes para a rede
externa (Internet). A utilização da filtragem de pacotes pode alertar para ocorrências anormais,
tomando atitudes para informar o ocorrido ao dono da máquina ou simplesmente "logando" (gravando
informações sobre os dados que trafegam) tudo. Isso pode servir para uma análise posterior de
ocorrências anormais ou mesmo para usuários curiosos por saber o que a máquina (ou quem a opera
na rede) anda fazendo.
Filtragem de Pacotes em Linux
O kernel do Linux provê filtragem de pacotes desde a versão 1.1. A primeira geração, baseada no ipfw para
BSD, foi portado por Alan Cox em 1994. Em seguida o pacote foi aprimorado por Jos Vos com a ajuda de outros
interessados da comunidade Linux e adicionado à versão 2.0 com o nome de ipfwadm que controlava as regras
de filtragem no kernel. Em meados de 1998, Rusty Russel, com o apoio de Michael Neuling desenvolveram a
solução para incorporar ao kernel 2.2, o ipchains. E, finalmente, a quarta geração de ferramentas de filtragem
vem surgindo desde meados de 1999 com o nome de iptables..
Para utilizar este novo conjunto de ferramentas de filtragem, você precisa ter um kernel compilado com os
recursos do netfilter.
Netfilter é um ambiente geral presente nos kernels a partir do instável 2.3 (e em definitivo na versão 2.4), que
dá suporte aos módulos do iptables. Os módulos do netfilter só são encontrados nos kernels de versão
2.3.15 ou superiores. E são ativados marcando-se `Y' to CONFIG_NETFILTER na configuração do kernel
(antes de compilar).
A ferramenta iptables faz chamadas ao kernel utilizando os módulos de suporte para a filtragem de pacotes.
Iptables
A ferramenta iptables insere e retira regras da tabela de filtragem de pacotes do kernel. Para que as regras não
se percam no "reboot" da máquina, faz-se uso de scripts que são lidos a cada reinicialização e atualizados durante
a utilização da ferramenta, não havendo a necessidade de reconfiguração da tabela de regras manualmente a
cada vez que a máquina é ligada. (se bem que, um filtro de pacotes de uma rede não deve ser reinicializado
constantemente, principalmente em se tratando de Linux).
Iptables é, portanto, um substituto para as ferramentas ipfwadm e ipchains, com substanciais recursos
adicionados. Para minimizar as restrições ao processo de migração por quem já utilizava os antigos pacotes de
filtragem, existem módulos de suporte a essas ferramentas no novo kernel, embora seja aconselhável migrar
definitivamente para o novo pacote e aproveitar seus novos recursos.
Configurando Tabelas de Regras Permanentes
Como a configuração do firewall está armazenada no kernel e pode ser perdida em um reboot, é necessária a
criação de arquivos (scripts) como iptables-save e iptables-restore e incorporados à
inicialização da máquina (scripts de inicialização) para automatizar o processo de
inicialização do filtro de pacotes.
Implementação de Filtro de Pacotes Micros com Conexão Discada
Muitas pessoas utilizam uma conexão simples (PPP) para acesso à Internet, e desejam que durante a conexão
nada "entre" em sua rede ou máquina pessoal. Um script baseado em Netfilter/Iptables seria algo do tipo:
## Se você compilou como modulo o connection-tracking, descomente as linhas abaixo
# insmod ip_conntrack
# insmod ip_conntrack_ftp
## Crie a 'chain'
iptables -N block
iptables -A block
iptables -A block
iptables -A block
block para bloquear acessos de estranhos
-m state --state ESTABLISHED,RELATED -j ACCEPT
-m state --state NEW -i ! ppp0 -j ACCEPT
-j DROP
## Direcione (jump) as 'chains' INPUT e FORWARD para sua chain block.
iptables -A INPUT -j block
iptables -A FORWARD -j block
Funcionamento Interno
O kernel inicia com três listas de regras chamadas firewall chains (ou just chains). São elas : INPUT, OUTPUT e
FORWARD, que funcionam de forma diferente das ferramentas que utilizavam versões 2.0 e 2.2 do kernel.
_____
Incoming
/
\
Outgoing
-->[Routing ]--->|FORWARD|------->
[Decision]
\_____/
^
|
|
v
____
___
/
\
/
\
|OUTPUT|
|INPUT|
\____/
\___/
^
|
|
----> Local Process ---No esquema acima, são representadas as três 'chains'. Quando um pacote atinge uma das chains, esta examina o
seu cabeçalho e (baseada em sua tabela de regras) decide o que fazer com o pacote. Se a chain determina que
DROP o pacote, ele é descartado neste momento, caso contrário (ACCEPT) o pacote segue conforme o diagrama.
Uma chain é como uma lista de checagem de regras. O funcionamento se dá assim: se o cabeçalho do pacote
atender aos requisitos da regra, o pacote seguirá o destino (jump to) imposto pela regra, caso contrário, passará
adiante e será avaliada pela próxima regra, até que não haja mais regras para consultar. Daí então o kernel
verificará a política de segurança adotada pelas chains para decidir o que fazer com o pacote. Em sistemas
preocupados realmente com segurança (alvos mais visados), a política de segurança faz com que o kernel barre
(DROP) o pacote.
♦Quando um pacote chega (ou seja, passa pela placa de rede), o kernel primeiro verifica o destino do pacote.
Este procedimento é chamado roteamento (routing);
♦Se o pacote é destinado à máquina em questão (ou à rede interna), o pacote é enviado ao conjunto de regras
(como no diagrama), mais precisamente à chain INPUT, que o encaminhará (ou não) a algum processo que o
está esperando;
♦Em alguns casos, se o forwarding não estiver habilitado no kernel, ou ele não dispuser de regras que
redirecionem o pacote, o pacote será barrado (dropped). Se o forwarding estiver habilitado, e o pacote
estiver destinado a outra interface de rede, então o pacote seguirá (no diagrama) para a chain FORWARD, que
observará suas regras de forwarding e se ela aceitá-la (ACCEPT) o pacote será enviado adiante.
♦Um programa rodando na máquina em questão (ou em estações da rede interna) pode enviar pacotes pela rede.
Esses pacotes seguirão imediatamente para a chain OUTPUT e se suas regras não o barrarem (ACCEPT) o
pacote seguirá através da interface de saída para o seu destino.
Usando iptables
O iptables é similar ao ipchais, só que com várias características incorporadas. As três 'chains' padrão
permanecem (INPUT, OUTPUT e FORWARD). Estas chains não podem ser apagadas, embora, como no
iptables, novas chains podem ser criadas e apagadas. As principais operações de manipulação de chains do
iptables são :
-N
-X
-P
-L
-F
-Z
Cria uma nova chain
Deleta uma chain (vazia)
Muda as regras para uma chain padrão
Lista as regras de uma chain
"Flush" as regras fora da chain
Zera os pacotes e 'byte counters' de todas as regras de uma chain
Existem muitos meio de manipular regras dentro de uma chain:
-A
-I
-R
-D
-D
Acrescenta uma nova regra a uma chain
Insere uma nova regra em alguma posição em uma chain
Substitui uma regra em alguma posição em uma chain
Apaga uma regra em alguma posição em uma chain
Apaga a primeira regra que comparar em uma chain
O iptables na inicialização da Máquina
O iptables pode ser um módulo, chamado ('iptable_filter.o'), que poderia ser carregado
automaticamente na primeira vez em que rodamos o iptables, ou também pode estar dentro do kernel
permanentemente (compilado junto com o kernel).
Antes de qualquer comando do iptables ser acionado (supondo que não esteja sendo inicializado através dos
scripts de inicialização da distribuição), não há regras em qualquer chain padrão (INPUT, FORWARD e OUTPUT),
Todas as chains têm a política de aceitação (ACCEPT). Você pode alterar a política default da chain FORWARD para
prover a opção 'forward=0' para o módulo iptable_filter.
Manipulando Regras com Simplicidade
Este é o "feijão com arroz" da filtragem de pacotes; manipulação de regras. Muito provavelmente você usará os
comandos append (-A) e o delete (-D). Os outros (-I para inserir e -R para substituir) são simples
extensões desses dois conceitos.
Cada regra especifica que condições o pacote precisa satisfazer, e para onde ele deve seguir (target). Por
exemplo, você pode desejar barrar todos os pacotes ICMP vindos do endereço IP 127.0.0.1:
♦Condições : protocolo = ICMP; endereço IP de origem = 127.0.0.1
♦Alvo (target) = 'DROP'
127.0.0.1 é nossa interface 'loopback' (localhost) utilizada como exemplo. Utilizaremos o programa
'ping' para gerar os pacotes (ele simplesmente envia pacotes ICMP tipo 8 [echo request] aguardando
como resposta um pacote ICMP tipo 0 [echo reply].
# 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
Aplicando a regra :
# iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP
Teremos então como resposta :
# 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
#
Antes de aplicarmos a regra do iptables, o ping com o parâmetro -c 1 (envio de somente um pacote) foi bem
sucedido, obtendo o echo reply.
Quando nós adicionamos (-A) à chain INPUT, a regra especificou que para pacotes vindos de 127.0.0.1 (-s
127.0.0.1) com protoloco ICMP (-p icmp) deveriam saltar (jump) para o DROP (-j DROP).
Quando nós testamos nossa regra, usando novamente o ping, houve uma pausa (a solicitação espera por uma
resposta que nunca vem), e em seguida a mensagem de que o pacote foi perdido (100% packet loss).
Essa regra pode ser apagada de duas maneiras. Ou deletando diretamente pelo número da regra na chain
INPUT:
# iptables -D INPUT 1
Ou substituindo o comando -A por -D na linha de inserção da regra :
# iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP
A sintaxe do -D tem exatamente as mesmas opções dos comandos -A, -I ou -R. Se existirem muitas regras
idênticas na mesma chain, somente a primeira será apagada.
Especificando a Filtragem
Já vimos a utilização do -p para especificar o protocolo, e -s para especificar o endereço de origem, mas há
ainda outras opções que podem ser usadas para especificar características de uma regra de filtragem de pacotes..
Origem (source)
Destino (destination)
`-s', `--source' ou `--src'
`-d', `--destination' ou `--dst'
A origem ou o destino podem ser especificadas de quatro formas:
♦full name : como `localhost' ou `www.linuxhq.com'
♦Endereço IP : como `127.0.0.1'
♦Grupo de endereços IP : do tipo `199.95.207.0/24' ou `199.95.207.0/255.255.255.0'
Os dígitos após a barra '/' são a máscara de rede utilizada para definir os IP's que estão englobados no grupo.
'/32' ou '/255.255.255.255' representam o padrão. Para especificar algum endereço IP entre todos,
podemos usar '/0'.
[ OBS: `-s 0/0' é redundante aqui. ]
# iptables -A INPUT -s 0/0 -j DROP
Especificando uma Inversão (!)
Muitas flags, inclusive a -s e -d podem ter seus argumentos precedidos por (!) (pronucia-se 'not') para se
referir a endereços diferentes (NOT equal) dos apresentados.
Por exemplo: '-s ! localhost' refere-se a todos os pacotes não vindos 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 o valor numérico do protocolo por IP), ou um nome para os casos especiais de `TCP', `UDP' ou
`ICMP'. O nome do protocolo também pode (como as flags descritas acima) serem prefixados por um (!) , para
invertê-lo. Por exemplo `-p ! TCP' para especificar pacotes não TCP.
Especificando uma Interface
Interface de Entrada
Interface de Saída
`-i' (ou `--in-interface')
`-o' (ou `--out-interface')
Pacotes atravessando a chain INPUT não passam por uma interface de saída (output), assim, qualquer regra
usando -o nesta chain é inútil. Igualmente, pacotes que atravessam a chain OUTPUT não passam por uma
inteface de entrada (input), assim, qualquer regra usando -i nesta chain é inútil.
Somente pacotes que atravessam a chain FORWARD passam por ambas as interfaces (input e output).
Como uma situação especial, o nome de uma interface pode terminar com um '+' (como um coringa a fazer
referência a todas as interfaces, existentes ou não). Por exemplo, para especificar uma regra que abranja todas
as interfaces PPP, a opção utilizada poderia ser -i ppp+
A inversão também é válida para a interface, assim, o nome de uma interface precedido por um (!) , refere-se a
pacotes que não utilizam a(s) interface(s) especificada(s).
Especificando Fragmentos
Algumas vezes um pacote é muito grande para ser enviado todo de uma vez. Quando isso acontece, o pacote é
dividido em fragmentos e enviados como múltiplos pacotes. No destino, estes fragmentos são montados,
reconstruindo o pacote original.
O problema com fragmentos é que o primeiro deles tem a informação completa do campo de cabeçalho (IP +
TCP, UDP e ICMP) para serem examinados, mas os pacotes seguintes somente tem uma parte do cabeçalho (IP
sem o campo de protocolo adicional). E não é possível olhar o interior dos fragmentos do pacote seguintes em
busca da informação omitida (extensões do protocolo TCP, UDP e ICMP).
Se você utiliza técnicas de NAT ou tracking em suas conexões, não haverá com o que se preocupar, pois o pacote
será recomposto sempre antes de passar pelo filtro de pacontes.
Quando isso não acontece, as regras de filtragem procuram por informações sobre o pacote e não encontram.
Isso acontece porque o primeiro fragmento (com as informações completas) é tratado como um pacote qualquer,
já os demais fragmentos não.
Nesses casos a regra -p TCP --sport www especifica a porta de origem do 'www', o oposto desta regra seria
-p TCP --sport ! www.
De outra torma, você pode especificar uma regra especificamente para fragmentos posteriores, usando a flag
`-f' (ou `--fragment'). Isto também é usado para inserir uma regra que não se aplica aos fragmentos
posteriores, usando a inversão '!' precedendo a flag '-f'
Como exemplo, veja uma regra para barrar (drop) fragmentos vindos de 192.168.1.1:
# iptables -A OUTPUT -f -d 192.168.1.1 -j DROP
Extensões ao iptables: Novas combinações
O pacote iptables é extensível, ou seja, os recursos incorporados ao kernel juntamente com a ferramenta iptables,
podem ser combinados para prover novas características.
Algumas destas extensões são triviais, e outras bem "exóticas". Extensões podem ser feitas por outras pessoas e
distribuídas separadamente para outros usuários.
As extensões do kernel normalmente estão situadas no subdiretório de módulos do kernel, como em /lib/
modules/2.4.0/net. Estas extensões destão disponíveis para leitura se o kernel foi compilado com o
parâmetro CONFIG_KMOD marcado, para não precisar inserí-lo manualmente.
Já as extensões do programa iptables são bibliotecas normalmente localizadas em /usr/local/lib/
iptables/, dependendo da distribuição, também poderiam estar em /lib/iptables
ou
/usr/lib/iptables.
As extensões podem ser de dois tipos: novos alvos (targets) ou novas combinações (matches). Alguns
protocolos oferecem automaticamente novos testes que podem ser implementados na linha de comando após a
opção '-p', para ler a extensão equivalente ao novo teste explicitado, com a opção '-m' responsável pela
leitura da extensão.
Para visualizar o help de uma extensão, use a opção para lê-la (`-p', `-j' ou `-m') seguida de `-h' ou
`--help', por exemplo:
# iptables -p tcp --help
Extensões TCP
As extensões TCP são automaticamente carregadas se a opção `-p tcp' é especificada. Em seguida, então,
pode-se adicionar as opções desejadas, detalhadas a seguir:
--tcp-flags
Utilizada para filtrar flags específicas, (ou não, em caso de precedida de ). A primeira string de flags é a
máscara (uma lista de flags para examinar) e a segunda string sinaliza qual(is) flags serão selecionadas,
por exemplo :
# iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DENY
Isto indica que todas as flags serão examinadas ('ALL' é equivalente a informar 'SYN,ACK,FIN,RST,
URG,PSH'), mas somente SYN e ACK serão selecionadas. Existe também o argumento 'NONE' para
indicar nenhuma flag.
--syn
Opcionalmente precedida por um '!', esta opção é a abreviação para `--tcp-flags SYN,RST,ACK
SYN'.
--source-port (ou -sport)
Opcionalmente precedida por um '!', utilizada para indicar uma porta TCP, ou uma lista de portas. As
portas podem ser indicadas por nomes, (indicadas em /etc/services , ou por seus números
equivalentes). A lista de portas deve ter seus nomes (ou números) separados por um ':'
--destination-port (ou -dport)
De utilização semelhante ao anterior, só que especifica a(s) porta(s) de destino ao invés de origem.
--tcp-option
Precedido opcionalmente por um '!', e um número, compara um pacote com uma opção TCP igual a um
número. Um pacote que não tenha um cabeçalho TCP completo é barrado (drop) automaticamente se esta
opção estiver formulada para examinar esta situação.
Explicando Flags TCP
Algumas vezes desejamos que uma máquina aceite conexões TCP em uma direção, mas não em outra. Por
exemplo, uma máquina aceita conexões para um servidor WWW externo, mas não aceita conexões vindas deste
servidor.
A primeira solução poderia ser bloquear pacotes TCP vindos do servidor, porém, em conexões TCP pacotes
necessitam trafegar em ambas as direções para consolidar as negociações de conexão.
A solução seria, então, bloquear somente pacotes usados para requisitar uma conexão. Estes pacotes são
chamados pacotes SYN (tecnicamente falando, são pacontes com a flag SYN habilitada, e as flags FIN e ACK
desabilitadas, mas nós chamaremos de pacotes SYN para facilitar). Se rejeitarmos somente estes pacotes, nós
poderemos barrar tentativas de conexão, indentificando-as por esta característica.
A flag `--syn' é utilizada para isto: isto só é válido especificamente para protolocos TCP. Por exemplo, para
especificar uma conexão TCP vindo de 192.168.1.1:
-p TCP -s 192.168.1.1 --syn
A inversão também pode ser aplicada nesses casos para se obter o inverso do descrito na sentença.
Extensões UDP
Extensões UPD são lidas automaticamente se a opção `-p udp' for especificada. As opções `--sourceport', `--sport', `--destination-port' and `--dport' funcionam para este protocolo de maneira
semelhante à explicada para o protocolo TCP.
Extensões ICMP
Extensões ICMP são lidas automaticamente se a opção `-p icmp' for especificada. Para esta extensão, existe
somente uma nova opção:
--icmp-type
Opcionalmente precedida por um '!', pode ser utilizada informando por nome (por exemplo: `hostunreachable'), ou um código numérico (padrão do protocolo icmp, por exemplo '3'), ou ainda, o tipo e
o código separados por uma barra '/' (ex. `3/3'). Uma lsita dos códigos numéricos disponíveis
para o protocolo icmp pode ser visualizada, utilizando-se `-p icmp --help'.
Outras Extensões
As outras extensões no paconte netfilter são extensões de demonstração, que podem ser acionadas (se
instaladas previamente) com a opção `-m'.
♦mac
Este módulo pode ser explicitamente especificado com a opção `-m mac' ou `--match mac'. E é
utilizada para fazer filtragens dentro do código do pacote, baseadas no endereço (MAC) Ethernet, e
somente é utilizada em pacotes em pré-roteamento (PREROUTING) e chains INPUT. Dispõe de uma
única opção:
--mac-source
Opcionalmente precedida por um '!', informa o endereço ethernet para consulta em notação hexbite,
como no exemplo: `--mac-source 00:60:08:91:CC:B7'.
♦limit
Este módulo pode ser explicitamente especificado com a opção `-m limit' ou `--match limit'
e é usada para restringir o número de buscas (matches), evitando o excesso de mensagens de log.
Com a opção habilitada, a regra fitrará (e consequentemente logará) um número limite de vezes por
segundo (por default 3 'matches' por hora, ou no máximo 5). Esta opção tem 2 argumentos opcionais:
--limit
Seguido de um número, especifica o número médio máximo de 'matches' aceitos por segundo. Este
número pode ser especificado em outras unidades de tempo, usando `/second', `/minute',
`/hour' ou `/day', ou parte deles (por exemplo : `5/second' assim como `5/s').
--limit-burst
Seguido de um número, indica o número máximo de 'matches' que extrapolem o limite.
Esta opção pode ser usada com o alvo (TARGET) LOG para definir o limite de 'logging'. Na prática, algo
como o exemplo a seguir:
# iptables -A FORWARD -m limit -j LOG
O primeiro objetivo desta regra está sendo atingido, o pacote será logado; porém, até o limite default de 5,
ou seja, os 5 primeiros pacotes serão logados. Após isso, a regra só voltará a logar os pacotes após 20 minutos,
independente da quantidade de pacotes que passem por ela neste período.
Se dentro de 20 minutos a regra não for utilizada, o limite suportará um log a mais. Se nenhum pacote
utilizar a regra por 100 minutos, o limite será zerado.
Este módulo pode ser utilizado para detectar e prevenir vários ataques do tipo 'denial of service' (ataques
de negação de serviço) DoS,
¾Proteção contra Syn-floods
# iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT
¾Port scanners ocultos
# 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
♦owner
Este módulo ajuda a localizar várias características do criador de pacotes gerados internamente. Esta
opção somente é válida para a chain OUTPUT, e detecta quando alguns pacotes (como respostas a
ping's ICMP) não possuem dono, e consequentemente nunca chegarão ao destino.
--uid-owner userid
Ativa a regra se o pacote foi criado por um processo concebido efetivamente pelo (número) user id.
--uid-owner groupid
Ativa a regra se o pacote foi criado por um processo concebido efetivamente pelo (número) group id.
--pid-owner processid
Ativa a regra se o pacote foi criado por um processo concebido efetivamente pelo (número) process id
--sid-owner processid
Ativa a regra se o pacote foi criado por um processo concebido pelo session group.
♦unclean
Este módulo experimental pode ser explicitamente especificado com a opção `-m unclean ou `-match unclean'. Ele realiza várias checagens aleatórias em pacotes. Este módulo não foi auditado,
e não poderia ser usado como um mecanismo de segurança (ainda pode conter bugs internos).
O Estado "Match"
A utilização mais conveniente para a opção 'match' é fornecida pela extensão 'state', que interpreta a e
analisa a conexão do módulo `ip_conntrack'. Ela é altamente recomendada.
Especificamente, a opção `-m state' aceita uma opção adicional `--state', que é uma lista de estados de
ativação separados por vírgula. (a flag '!' não indica a ativação deses estados). Esses estados são:
NEW
Um pacote que cria uma nova conexão.
ESTABLISHED
Um pacote que pertence a uma conexão existente (isto é, um pacote de resposta).
RELATED
Um pacote que está relacionado com (mas não faz parte de) uma conexão existente, como um ICMP
error, ou (com o módulo FTP inserido), um pacote que estabelecido por uma conexão de dados ftp.
INVALID
Um pacote que não poderia ser identificado por alguma razão: isto inclui execução fora da memória e
erros de ICMP que não correspondam a nenhuma conexão existente. Geralmente estes pacotes devem
ser barrados (drop).
Especificações de Alvos (TARGET's)
Após examinar um pacote, é necessário indicar um destino para o mesmo, caso seja ativada alguma das regras.
Isto é chamado de regra de alvo (rule's target).
Os dois alvos mais comumente utilizados em um filtro de pacotes são o DROP para barrar o pacote e o ACCEPT
para aceitá-lo. Se uma regra é ativada e o alvo é um destes dois, nenhuma regra mais é consultada, o destino do
pacote já foi decidido.
Existem, ainda, outros dois outros tipos de alvos: extensões e chains definidas pelo usuário.
Chains definidas pelo usuário
Uma das funções que o iptables herdou do ipchains é a possibilidade do usuário criar novas chains,
complementando as três chains padrão (INPUT, FORWARD and OUTPUT). Por convenção, as chains definidas
pelo usuários são compostas por letras minúsculas para distingui-las. Mais adiante, as chains definidas pelo
usuários serão mais detalhadas.
Quando um pacote ativa uma regra cujo alvo é uma chain definida pelo usuário, o pacote segue atravessando a
regra da chain definida pelo usuário. Se a chain não decide o destino do pacote, então o pacote passará para a
próxima regra da chain corrente.
Veja o exemplo gráfico a seguir. Consedere duas chains bem simples: INPUT (a chain padrão) e test (uma chain
definida pelo usuário)
`INPUT'
----------------------------| Regra1: -p ICMP -j DROP
|
|---------------------------|
| Regra2: -p TCP -j test
|
|---------------------------|
| Regra3: -p UDP -j DROP
|
-----------------------------
`test'
----------------------------| Regra1: -s 192.168.1.1
|
|---------------------------|
| Regra2: -d 192.168.1.1
|
-----------------------------
Considere um pacote TCP vindo de 192.168.1.1, indo para 1.2.3.4. Ele entra na chain INPUT, e é testada
pela Regra1 - não ativa. Regra2 - ativa, e o alvo é test, então a próxima regra examinada é o início de test.
Regra1 de test - ativa, mas não especifica um alvo, então a próxima regra é examinada (a Regra2 de test) - não
ativa, e chegamos ao fim da chain test. O pacote então retorna à chain INPUT e irá passar para a regra seguinte à
que a ativou (Regra2). Regra3 - não ativa. O pacote passa então pelo conjunto de regras sem restrições. O fluxo
desta operação é mostrado abaixo:
v
___________________________
`INPUT'
|
/
`test'
v
-------------------------|--/
------------------------|---| Regra1
| /|
| Regra1
|
|
|------------------------|/-|
|-----------------------|---|
| Regra2
|
| Regra2
|
|
|---------------------------|
------------------------v---| Regra3
/--+____________________________/
-------------------------|--v
Chains definidas pelo usuário podem pular para outras chains definidas pelo usuário (porém cuidado com loops,
seus pacotes podem ser barrados se o conjunto de regras entrar em loop).
Extensões para iptables : Novos Alvos (new targets)
Um outro tipo de alvo é uma extensão. Um alvo extensão consiste em um módulo do kernel, uma extensão
opcional para o iptables para prover novas opções de linhas de comando. Há muitas extensões na distribuição
padrão do netfilter:
♦LOG
Este módulo provê o log (logging) a nível de kernel de pacotes que ativem regras de filtragem. Existem
algumas opções adicionais:
--log-level
Seguido por um número de nível (level number) ou nome. Os nomes válidos são (em minúsculas):
`debug', `info', `notice', `warning', `err', `crit', `alert' e `emerg',
correspondendo aos números de 7 a 0. Veja a página de manual (man page) do syslog.conf para um
melhor detalhamento desses níveis.
--log-prefix
Seguido por uma string de até 30 caracteres, esta mensagem é "impressa" no início da mensagem de
log, (para facilitar a identificação de mensagens emitidas pelo iptables por parte de programas de
tratamento de log, sem confundí-las com as de outros serviços logados pelo syslog). Este módulo é
muito usado após um alvo limite, porém, cuidado para não inundar ("floodar") seus logs.
♦REJECT
Este módulo tem o mesmo efeito que o 'DROP', exceto pelo fato de que ele envia uma mensagem de
erro à origem do pacote (ICMP 'port unreachable').
OBS: A mensagem de ICMP error não será enviada se (mais detalhes na RFC 1122) :
o O pacote que está sendo filtrado contiver uma mensagem de erro ICMP no início, ou algum tipo de
ICMP desconhecido (unknown ICMP type);
o O pacote que está sendo filtrado for um fragmento que não pertence ao cabeçalho;
o Foram enviados muitos pacotes com mensagens de erro ICMP para este destino recentemente.
REJECT também possui o argumento opcional `--reject-with' que altera a resposta ao pacote (veja a
página de manual para mais detalhes)
Alvos padrão Especiais
Existem 2 alvos padrão especiais: RETURN e QUEUE.
♦RETURN tem o mesmo efeito de não-ativação ao final de uma chain: para uma regra de com uma chain padrão,
a política da chain é executada. Para uma regra definida pelo usuário, retorna à chain anterior, obedecendo
às regras após o alvo que implicou no salto para a regra em questão.
♦QUEUE é um alvo especial, que enfileira (QUEUE) o pacote para um "userspace processing". Para
implementar isto, 2 componentes adicionais são requeridos:
o Uma "queue handler", que trabalhe conjuntamente com o atual mecanismo de passagem de pacotes
entre o kernel e o o "userspace" ; e
o Uma aplicação "userspace" para receber, (possivelmente manipular), e emitir um veredicto sobre o
pacote.
O modelo de "queue handler" para IPv4 iptables é o módulo ip_queue, que é distribuído com o kernel e
marcado como experimental (até a presente versão em desenvolvimento).
Eis um exemplo de como usar o iptables para "queue" pacotes para "userspace processing" :
# modprobe iptable_filter
# modprobe ip_queue
# iptables -A OUTPUT -p icmp -j QUEUE
Com esta regra, pacotes ICMP de saída gerados localmente (com se fossem criados com ping), são passados
para o módulo ip_queue, que então providencia o envio dos pacotes para uma aplicação "userspace". Se
nenhuma aplicação userspace estiver na espera, os pacotes são barrados (dropped).
Para escrever uma aplicação userspace, utilize a API libipq. Esta API é distribuída com o iptables. Exemplos
de códigos podem ser encontrados nas ferramentas de teste (como o redirect.c) presente no CVS.
O status do ip_queue pode ser checado via:
/proc/net/ip_queue
O comprimento máximo da queue (isto é, o número de pacotes enviados ao userspace com o veredicto não
emitido retornado), pode ser controlado via:
/proc/sys/net/ipv4/ip_queue_maxlen
O valor padrão para o comprimento máximo do queue é 1024. Sempre que este limite for ultrapassado, novos
pacotes serão barrados após o comprimento da queue atingir o seu limite. Alguns protocolos como o TCP
interpreta a barragem de pacotes como congestionamento, e aguardará a queue retornar. Outras vezes, ele pode
experimentar determinar um comprimento máximo ideal da queue para uma próxima situação se o valor padrão
form muito pequeno.
Operando uma chain corretamente
A melhor característica de uso do iptables é a habilidade para regras de grupos relacionados nas chains. Você
pode chamar uma chain como você desejar, porém é recomendável utilizar letras minúsculas para evitar
confusões com as chains e alvos padrão. Os nomes das chains podem ter 31 letras de comprimento.
Criando uma nova chain
Chamaremos nossa primeira chain de test. Para criá-la podemos utilizar a opção `-N' ou `--new-chain':
# iptables -N test
Pronto. Basta agora definir os detalhes da nova chain e as regras que irão utilizá-la.
Deletando uma chain
Para deletar uma chain podemos utilizar a opção `-X' ou `--delete-chain'
# iptables -X test
Há um par de restrições para deletar chains:
•Não pode haver regras ativas que contenham estas chains; e
•As chains não podem ser alvos de nenhuma regra.
OBS1: Você não pode deletar as 3 chains padrão.
OBS2: Se não for especificada a chain a deletar, todas as chains definidas pelo usuário serão deletadas (se
possível)
Descarregando (flushing) uma chain
Existe um simples caminho para descarregar todas as regras para fora de uma chain, usando o comando `-F'
(ou `--flush').
# iptables -F forward
Se não for especificada uma chain, todas as chains serão descarregadas.
Listando uma chain
Você pode listar todas as regras de uma chain usando o comando `-L' (ou `--list').
A `refcnt' listada por cada chain definida pelo usuário é o número de regras que têm esta chain como alvo. Ela
deve ter valor zero (e a chain estar vazia) antes desta chain ser deletada. Se o nome da chain for omitido, todas
as chains serão listadas, inclusive as vazias. Existem 3 opções que podem acompanhar `-L':
♦A opção (numérica) `-n' é muito usado para tentar fazer o iptables examinar o reverso do endereço IP, que (se
você estiver usando o DNS como muitas pessoas) causará longas esperas (delays) se seu DNS não estiver
configurado adequadamente, ou se houverem regras de filtragem de saídas de requisições DNS. Isto também
faz com que as portas TCP e UDP sejam impressas como números antes dos nomes.
♦A opção '-v' exibe todos detalhes das regras, assim como os pacotes e os 'byte counters', as
comparações TOS, e as interfaces. Em alguns casos estes valores são omitidos. Os pacotes e 'byte
counters' são exibidos usando os sufixos `K', `M' ou `G' para abreviar 1.000, 1.000.000 e
1.000.000.000 respectivamente.
♦Usando a flag `-x' (expand numbers) é utilizada para uma boa exibição de números sem abreviá-los, não
importando que tamanho tenham.
Zerando Contadores
Para resetar contadores (counters), utiliza-se a opção `-Z' (ou `--zero').
O problema com este recurso é que algumas vezes você precisa informar os valores dos contadores
imediatamente antes que eles sejam resetados.
Compatibilidade com pacotes antigos
Existem módulos na distribuição netfilter chamados ipchains.o e ipfwadm.o. Estes recursos foram
incorporados para administradores de firewall já acostumados aos antigos pacotes, porém, não detalharemos aqui
(embora o documento fonte fale a respeito) por ser incompatível com os novos recursos que utilizaremos, a saber,
iptables.o, ip_conntrack.o e ip_nat.o.
Mesclando NAT e Filtragem de Pacotes
É muito comum utilizar em um firewall recursos de NAT (Network Address Translation) juntamente com filtragem
de pacotes. O iptables realiza esta tarefa extremamente bem sem a necessidade de pacotes adicionais.
É possível implemenar a filtragem de pacotes ignorando completamente qualquer NAT, se você desejar. As
origens e destinos "enxergadas" pelos pacotes serão as origens e destinos "reais".
Por exemplo, se você fez DNAT para enviar conexões direcionadas para o IP 1.2.3.4 porta 80 através do IP
10.1.1.1 porta 8080, o filtro de pacotes poderia enxergar os pacotes indo para 10.1.1.1 porta 8080 (o destino real)
e não para 1.2.3.4 porta 80.
Você pode, também, ignorar o mascaramento (masquerading), fazendo com que pacotes enxerguem seus
endereços IP's internos reais (como 10.1.1.1), e respondam através dele.
Você pode utilizar a extensão 'state' sem trabalhar com o filtro de pacotes, desde que o NAT solicite conexão
de qualquer modo.
A seguir, um exemplo simples de mascaramento utilizando NAT para desabilitar qualquer nova conexão vindo da
interface ppp0:
# Mascarando a saída pela interface ppp0
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
# Desabilitando solicitações novas (NEW) e inválidas (INVALID) ou
# pacotes enviados da interface ppp0.
iptables -A INPUT -i ppp0 -m state --state NEW,INVALID -j DROP
iptables -A FORWARD -i ppp0 0 -m state --state NEW,INVALID -j DROP
# Habilitando o recurso de IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
Diferenças entre iptables e ipchains
♦Primeiramente, a escrita dos nomes das chains padrão foram modificados de maiúsculas para minúsculas, isso
porque no novo pacote, as chains INPUT e OUTPUT somente são utilizadas para destinos locais e pacontes
gerados localmente, para visualizar todos os pacotes que chegam e que saem respectivamente.
♦A flag '-i' agora indica a interface de entrada, e somente deve ser utilizada nas chains INPUT e FORWARD.
Regras das chains FORWARD (para saída) e OUTPUT que utilizavam '-i' devem agora utilizar '-o'.
♦As portas TCP e UDP agora precisam ser descritas com as opções --source-port ou --sport (ou -destination-port/--dport), e podem ser posicionadas após as opções `-p tcp' ou `-p udp' que
carregam as extensões TCP ou UDP respectivamente.
♦A flag TCP -y é agora --syn, e deve vir após a opção `-p tcp'.
♦O alvo (target) DENY é agora DROP, finalmente.
♦Chains únicas podem ser zeradas enquanto estão sendo listadas.
♦Ao zerar chains padrão, também são apagados os contadores da política.
♦Listando chains você implementa os contadores como um "snapshot" atômico.
♦REJECT e LOG são agora alvos extendidos, entendidos como módulos do kernel separados.
♦Os nomes das chains podem ter até 31 caracteres.
♦MASQ é agora MASQUERADE e utiliza uma sintaxe diferente. REDIRECT, embora tenha mantido o mesmo nome,
também sofreu modificações de sintaxe.
♦A opção -o não é mais utilizada para direcionar pacotes para dispositivos 'userspace'. Pacotes são agora
enviados ao userspace via alvo QUEUE.
Conselhos sobre Implementação de Filtragem de Pacotes
♦A prática comum na filtragem de pacotes é o bloqueio de todos os serviços, e a abertura de regras ncessárias.
Este procedimento é denominado "tudo o que não é explicitamente permitido é proibido". Este procedimento é
o mais recomendável para obter um nível de segurança maior.
♦Não rode nenhum serviço que você não precisa rodar, se você não sabe pra que serve, bloqueie o acesso a ele.
♦Se você está criando um firewall dedicado, inicie sem rodar nada, e bloqueie todos os pacotes, então adicione os
serviços necessários.
♦Outra recomendação do texto-original é combinar tcp-wrappers, proxies, verificação de rotas e filtragem de
pacotes. Barrar, por exemplo, pacotes com endereços de origem internos vindos de sua interface externa. Isto
pode ser habilitado para uma interface (ppp0) como em:
# echo 1 > /proc/sys/net/ipv4/conf/ppp0/rp_filter
Ou para uma uma interface que existirá numa operação futura, como:
# for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
#
echo 1 > $f
# done
♦Logging é útil na implementação de um firewall se algumas vezes ele não é utilizado. Para um bom desempenho
do firewall, sempre combine os logs com a flag 'limit', para prevenir possíveis floods em seus logs.
O autor do documento-texto recomenda, ainda, com veemência a utilização de connection tracking para
tornar o sistema mais seguro. Para isso, é necessário o carregamento do módulo `ip_conntrack.o' se o
módulo não é lido automaticamente pelo kernel. E ainda, se desejar exatamente track de protocolos complexos,
é necessário carregar o módulo apropriado (por exemplo, `ip_conntrack_ftp.o').
# iptables -N
# iptables -A
# iptables -A
# iptables -A
from ppp0:"
# iptables -A
not from ppp0:"
# iptables -A
no-conns-from-ppp0
no-conns-from-ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT
no-conns-from-ppp0 -m state --state NEW -i ! ppp0 -j ACCEPT
no-conns-from-ppp0 -i ppp0 -m limit -j LOG --log-prefix "Bad packet
no-conns-from-ppp0 -i ! ppp0 -m limit -j LOG --log-prefix "Bad packet
no-conns-from-ppp0 -j DROP
# iptables -A INPUT -j no-conns-from-ppp0
# iptables -A FORWARD -j no-conns-from-ppp0
Existem 3 sites oficiais tratando do assunto Netfilter/Iptables :
ƒFilewatcher <http://netfilter.filewatcher.org>
ƒThe Samba Team and SGI <http://www.samba.org/netfilter>
ƒJim Pick <http://netfilter.kernelnotes.org>
Para a lista de discussão oficial sobre o assunto, veja informações em :
ƒSamba's Listserver <http://lists.samba.org>
Adaptado do documento :
Linux 2.4 Packet Filtering HOWTO - Rusty Russell
mailing list [email protected]