Colocando filtros em Hash para filtragem pesada muito veloz :: Admirável Mundo Novo




Muito Bem Vindo

Prezado Leitor, a proposta desse Blog é compartilhar conhecimento com as pessoas que trabalham com Linux, Asterisk, OpenSER, e com tecnologia de voz sobre a rede IP em geral, através de tutoriais, dicas, howto, notícias entre outros assuntos.

Atente para termo de uso do conteúdo do blog no rodapé da página.

sexta-feira, 9 de janeiro de 2009

Colocando filtros em Hash para filtragem pesada muito veloz




12.4. Colocando filtros em Hash para filtragem pesada muito veloz

Se você tiver uma necessidade de milhares de regras, por exemplo, se você tiver grande quantidade de clientes ou computadores, todos com diferentes especificações de QoS, você pode achar que o kernel gasta muito tempo fazendo o batimento de todas essas regras.

Por padrão, todos os filtros residem em um grande encadeamento (chain) que é verificado em ordem descendente de prioridade. Se você tiver 1000 regras, 1000 verificações podem ser necessárias para determinar o que fazer com um pacote.

A verificação correria muito mais rápida se você tivesse 256 encadeamentos com quatro regras cada um – se você pudesse dividir os pacotes sobre esses 256 encadeamentos, de modo que a regra certa esteja lá.

A tabela hash torna isso possível. Digamos que você tenha 1024 clientes Cable Modem em sua rede, com faixa de endereço IP de 1.2.0.0 a 1.2.3.255, e cada qual está em uma categoria de serviço diferente, por exemplo ‘lite’, ‘regular’ e ‘premium’. Você então teria 1024 regras como essa:

# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
match ip src 1.2.0.0 classid 1:1

# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
match ip src 1.2.0.1 classid 1:1

...

# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
match ip src 1.2.3.254 classid 1:3

# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
match ip src 1.2.3.255 classid 1:2


Para aumentar a velocidade disso, nós podemos usar a última parte do endereço IP como uma ‘chave hash’. Nós então obtemos 256 tabelas, as primeiras das quais se parece com isso:

# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
match ip src 1.2.0.0 classid 1:1

# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
match ip src 1.2.1.0 classid 1:1

# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
match ip src 1.2.2.0 classid 1:3

# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
match ip src 1.2.3.0 classid 1:2


Os seguintes começam parecidos com isso:

# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
match ip src 1.2.0.1 classid 1:1
...


Esse caminho, somente quarto verificações são necessárias no máximo, duas na média.
A configuração é um tanto complicada, mas considera-a fortemente quando você tiver muitas regras dessas. Primeiro nós fazemos um filtro root, e então criamos uma tabela com 256 entradas:

# tc filter add dev eth1 parent 1:0 prio 5 protocol ip u32

# tc filter add dev eth1 parent 1:0 prio 5 handle 2: protocol ip u32 divisor 256


Agora adicionamos algumas regras a entrar na tabela criada:

# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: \
match ip src 1.2.0.123 flowid 1:1

# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: \
match ip src 1.2.1.123 flowid 1:2

# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: \
match ip src 1.2.3.123 flowid 1:3

# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: \
match ip src 1.2.4.123 flowid 1:2


Essa é a entrada 123, que contém conferências para 1.2.0.123, 1.2.1.123, 1.2.2.123, 1.2.3.123, e as envia para 1:1, 1:2, 1:3 e 1:2 respectivamente. Observe que precisamos especificar o nosso balde hash em hexadecimal, 0x7b é 123.


Segundo criamos um ‘filtro hashing’ que direciona o tráfego para a entrada certa na tabela hashing:

# tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 800:: \
match ip src 1.2.0.0/16 hashkey mask 0x000000ff at 12 link 2:


Ok, alguns números precisam de explicação. A tabela hash padrão é chamada 800:: e toda a filtragem começa lá. Então nós selecionamos o endereço origem, que reside como posição 12, 13, 14 e 15 no cabeçalho IP, e indica que nós estamos interessados somente na última parte. Isso será enviado para tabela hash 2: que nós criamos antes.

Isso é totalmente complicado, mas funciona na prática e o desempenho será incrível. Observe que esse exemplo pode ser melhorado para o caso ideal onde cada encadeamento contem 1 filtro!


12.5. Filtragem de Tráfego no IPv6
12.5.1. Como conseguir que os 'tc filter's no IPv6 não funcionem?

O DataBase de Controle de Roteamento – Routing Policy Database (RPDB) – substituiu o roteamento IPv4 e a estrutura de endereçamento dentro do Kernel Linux que levaram a todas as funcionalidades maravilhosa que esse HOWTO descreve. Infelizmente a estrutura IPv6 dentro do Linux foi implementado fora dessa estrutura núcleo. Embora eles compartilhem algumas facilidades, a estrutura RPDB essencial não participa internamente ou com endereçamento IPv6 e estrutura de roteamento.

Isso mudará certamente, apenas precisamos esperar um pouco mais.

CORRIJAM-ME: Algumas idéias se alguém estiver trabalhando nisso? Planeja?


12.5.2. Marcando pacotes IPv6 usando o ip6tables

O ip6tables é capaz de marcar um pacote e atribuir um número a ele:

# ip6tables -A PREROUTING -i eth0 -t mangle -p tcp -j MARK --mark 1


Mas ainda, isso não ajudará porque o pacote não atravessará a estrutura RPDB.


12.5.3. Usando o seletor u32 para bater com pacote IPv6

O IPv6 é normalmente encapsulado em um túnel SIT e transportado sobre redes IPv4. Veja a seção Tunelamento IPv6 para informações de como configurar tal túnel. Isso nos permite filtrar os pacotes IPv4 que manter os pacotes IPv6 como payload.


O filtro seguinte bate com todos os pacotes IPv6 encapsulados nos pacotes IPv4:

# tc filter add dev $DEV parent 10:0 protocol ip prio 10 u32 \
match ip protocol 41 0xff flowid 42:42


Permita-nos continuar com isso. Supondo que seus pacotes IPv6 são enviados sobre o IPv4 e esses pacotes não tem quaisquer opções definidas. Alguém pode usar o filtro seguinte para bater com ICMPv6 no IPv6 e no IPV4 sem quaisquer opções. O 0x3a (58) é o tipo Next-Header para ICMPv6.

# tc filter add dev $DEV parent 10:0 protocol ip prio 10 u32 \
match ip protocol 41 0xff \
match u8 0x05 0x0f at 0 \
match u8 0x3a 0xff at 26 flowid 42:42


Fazer o batimento do endereço IPv6 destino é um pouco mais trabalhoso. O filtro seguinte bate com o endereço destino 3ffe:202c:ffff:32:230:4fff:fe08:358d:

# tc filter add dev $DEV parent 10:0 protocol ip prio 10 u32 \
match ip protocol 41 0xff \
match u8 0x05 0x0f at 0 \
match u8 0x3f 0xff at 44 \
match u8 0xfe 0xff at 45 \
match u8 0x20 0xff at 46 \
match u8 0x2c 0xff at 47 \
match u8 0xff 0xff at 48 \
match u8 0xff 0xff at 49 \
match u8 0x00 0xff at 50 \
match u8 0x32 0xff at 51 \
match u8 0x02 0xff at 52 \
match u8 0x30 0xff at 53 \
match u8 0x4f 0xff at 54 \
match u8 0xff 0xff at 55 \
match u8 0xfe 0xff at 56 \
match u8 0x08 0xff at 57 \
match u8 0x35 0xff at 58 \
match u8 0x8d 0xff at 59 \
flowid 10:13


A mesma técnica pode ser usada para bater com sub-redes. Por exemplo, 2001::

# tc filter add dev $DEV parent 10:0 protocol ip prio 10 u32 \
match ip protocol 41 0xff \
match u8 0x05 0x0f at 0 \
match u8 0x20 0xff at 28 \
match u8 0x01 0xff at 29 \
flowid 10:13









Autores Originais dos textos:

Bert Hubert (Netherlabs BV)
bert.hubert@netherlabs.nl

Thomas Graf (Autor de Seção)
tgraf@suug.ch

Gregory Maxwell (Autor de Seção)
greg@linuxpower.cx

Remco van Mook (Autor de Seção)
remco@virtu.nl

Martijn van Oosterhout (Autor de Seção)
kleptog@cupid.suninternet.com

Paul B Schroeder (Autor de Seção)
paulsch@us.ibm.com

Jasper Spaans (Autor de Seção)
jasper@spaans.ds9a.nl

Pedro Larroy (Autor de Seção)
piotr@member.fsf.org







Nenhum comentário:




Creative Commons License
Admirável Mundo Novo: Tudo Sobre Asterisk, OpenSER, Linux e Tecnologias de Voz sobre IP
by Cléviton Mendes de Araújo is licensed under a Creative Commons Atribuição 2.5 Brasil License.