Controle de tráfego com TC, HTB e Iptables

De Eriberto Wiki
Ir para navegação Ir para pesquisar

by (C) João Eriberto Mota Filho <eriberto (a) eriberto pro br>

Artigo criado em: 19 de setembro de 2007.

Última atualização: veja o rodapé desta página.

Tiny URL ou bit.ly: http://bit.ly/htb_iptables



A importância do controle de tráfego

Imagine uma rede que possua Internet, com um link de 2 Mb/s, e 50 máquinas. Exemplos atuais: prédios, pequenas empresas, lan houses etc. Imagine ainda que nessa rede possa ser utilizado qualquer tipo de programa de acesso à Internet.

Numa rede liberal, programas como o EMule ou o Kazaa poderão causar um enorme congestionamento. Um único EMule instalado em um computador da rede poderá abrir dezenas de conexões simultâneas. Com isso, caso algum outro usuário, em outro computador, deseje visitar o GMail, por exemplo, teremos uma máquina, estabelecendo uma conexão, lutando contra outro computador com 60 conexões (apenas um exemplo). Teremos, em outras palavras, 01 contra 60. É óbvio que haverá uma grande desvantagem para um dos dois. Isso ocorre porque, da forma como o Kernel Linux trabalho, normalmente, os pacotes são enfileirados em um buffer e saem na mesma ordem em que chegaram (FIFO, para os mais experientes). Aumentar o link, ao contrário do que muitos desinformados pensam, não resolveria o caso, pois só estaríamos dando mais "poder de fogo" ao usuário do EMule e continuaríamos sendo o 60º da fila. O que fazer então? Duas soluções possíveis:

  • Bloquear o EMule, tornando-se um administrador radical e forçando o usuário de tal programa a achar uma forma de burlar o controle (sempre há uma forma de fazer isso). Ainda, o EMule foi bloqueado mas outros programas similares não. Existem centenas deles.
  • Controlar o tráfego da rede, fazendo com que haja um equilíbrio ou uma prioridade na navegação. Esta parece ser a forma mais sensata.


Controle de tráfego ou controle de banda?

  • Banda (ou bandwidth): é a diferença entre os limites superior e inferior de uma freqüência, geralmente medida em hertz.
  • Tráfego: quantidade de informações digitais transmitidas, geralmente medida em bits por segundo (b/s).


Assim, ao controlar um tráfego de rede estaremos realizando um controle de tráfego e não de banda, como muitos dizem. Para alterar as propriedades de uma banda, teremos que fazer alterações físicas no meio.

Unidades de medida

Observe as seguintes idéias:

  • Em tráfego de rede estaremos submetidos à base decimal e não à binária, como em processamento, armazenamento e memória. Assim, 1 KByte por segundo será igual a 1000 bytes por segundo.
  • A abreviatura de byte é B.
  • A abreviatura de bit é b.
  • 1 B = 8 b (um byte é composto por 8 bits).

Assim, 250 Kb/s são iguais a 31,25 KB/s que são iguais a 31250 B/s.

Classes

As classes são como corredores ou tubos, por onde passarão os pacotes. Assim, você poderá construir classes (tubos), estabelecer a velocidade máxima dentro de cada classe e definir quais tipos de pacotes poderão fluir por cada uma delas. Por exemplo: você poderá construir uma classe para e-mail e outra para sites, cada uma com uma velocidade máxima diferente.

Disciplinas de controle de tráfego

Existem muitas disciplinas de controle de tráfego. No Linux, tais disciplinas se dividem em classless e classful.

As disciplinas classless são simples, possuindo apenas uma classe. Com isso, não há a possibilidade de realizar a divisão de diferentes tráfegos. Podemos citar as seguintes disciplinas classless:

  • PFIFO (Packet First In First Out)
  • PFIFO Fast (Packet First In First Out Fast - default no Kernel Linux)
  • RED (Random Early Detection)
  • SFQ (Stochastic Fair Queuing)
  • TBF (Token Bucket Filter)
A disciplina TBF é excelente para limitar a velocidade máxima de uma placa de rede.



As disciplinas classful são mais eficientes e permitem a divisão do tráfego, priorizando cada tipo de conexão de acordo com as configurações utilizadas pelo administrador da rede. Podemos citar as seguintes disciplinas classful:

  • CBQ (Class Based Queueing)
  • HTB (Hierarchy Token Bucket)
  • PRIO (Priority class)

Atualmente, a melhor alternativa para o controle do tráfego é a associação do HTB com o PRIO.

O TC e as unidades de medida

No GNU/Linux, a implementação das disciplinas de controle de tráfego se dará com o comando tc. O tc utiliza as seguintes unidades de medida de velocidade de tráfego:

  • kbps - Kilobytes por segundo (KB/s)
  • mbps Megabytes por segundo (MB/s)
  • kbit Kilobits por segundo (Kb/s)
  • mbit Megabits por segundo (Mb/s)
  • bps Bytes por segundo (B/s)
É importante salientar novamente que quando medimos memória e processamento utilizamos a base 2 (binária). Assim, todas as grandezas de memória e processamento são múltiplas de 1024. No caso do controle de tráfego, a base é decimal e todas as grandezas serão múltiplas de 1000. Assim, 1 Mb/s = 1000 Kb/s = 125 KB/s.



Como funciona o HTB

O HTB funciona de forma hierárquica e, como todas as outras disciplinas, controla os pacotes que saem de uma determinada placa de rede. Isso se deve ao fato de que, quando um pacote chega a uma máquina, ele não pode ficar parado no cabo de rede ou na onda de rádio (wireless) esperando para entrar na placa. O pacote entra e é armazenado no buffer. Assim, só resta controlar a sua saída do buffer para a rede. Isso pode ser entendido com a figura a seguir:



Na imagem anterior, a interface eth0 irá controlar todo o download da Internet e a interface eth1 todo o upload.

No que tange à hierarquia, o HTB possui um elemento principal conhecido como root, que receberá a designação numérica 1:0 ou, simplesmente, 1:. O root possui um subordinado imediato, que controla o tráfego máximo total possível. Esse subordinado é uma classe e receberá a designação 1:1.

Os elementos superiores a cada classe são conhecidos como pais. A indicação para isso é parent.

A seguir um exemplo de configuração do root e do parent de controle total de tráfego, para a interface eth0, com o comando tc:

tc qdisc add dev eth0 root handle 1:0 htb default 40
tc class add dev eth0 parent 1:0 classid 1:1 htb rate 100mbit

A primeira linha estabelece o root, para a interface eth0, com a designação 1:0, usando a disciplina HTB. A palavra qdisc é a abreviatura de Queue discipline ou disciplina de enfileiramento. Em resumo, refere-se à disciplina de controle de tráfego. A primeira linha também estabelece que a classe default será a 1:40.

A classe default será utilizada para receber pacotes que não foram designados para trafegar em qualquer outra classe.

A segunda linha estabelece que a classe 1:0 será parent (pai) da 1:1. Esta classe estabelece que a interface de rede eth0 funcionará a 100 Mb/s.

Veja agora uma configuração do HTB já com algumas classes (dentro de um script em shell bash):

#!/bin/bash

tc qdisc del dev eth0 root

tc qdisc add dev eth0 root handle 1:0 htb default 40
tc class add dev eth0 parent 1:0 classid 1:1 htb rate 100mbit

tc class add dev eth0 parent 1:1 classid 1:10 htb rate 100kbit  ceil 300kbit  prio 0   # DNS / ACK / SYN / FIN
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 500kbit  ceil 800kbit  prio 1   # E-mail
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 1200kbit ceil 1600kbit prio 2   # HTTP / HTTPS
tc class add dev eth0 parent 1:1 classid 1:40 htb rate 300kbit  ceil 500kbit  prio 3   # Geral

A primeira linha remove qualquer pré-configuração existente. As duas linhas seguintes já foram analisadas. As próximas linhas são as classes que irão controlar o tráfego.

A classe 1:10 é filha da classe 1:1. Ela permitirá um tráfego de 100 Kb/s. Caso as outras classes estejam livres, sem tráfego, esta classe poderá emprestar um pouco do link que sobra nas outras, podendo chegar a 300 Kb/s. Esta classe tem prioridade 0, ou seja, todas as outras irão parar para o seu tráfego passar (caso isso seja necessário). No fim da linha há um comentário, que não é obrigatório. Por intermédio desse comentário, entendemos que a classe 1:10 será utilizada para tráfego DNS e para alguns pacotes com algumas flags TCP. A análise das demais classes segue o mesmo raciocínio. Apenas relembrando, a classe 1:40 é a classe default e, tudo que não for enviado para as outras classes terminará passando por ela.

A seguir, uma imagem que resume toda a situação explanada até aqui:



É interessante fazer uma configuração para a interface eth1 para controlar o upload. A configuração para a eth1 segue os mesmos princípios da eth0. Exemplo:

#!/bin/bash

tc qdisc del dev eth1 root

tc qdisc add dev eth1 root handle 1:0 htb default 40
tc class add dev eth1 parent 1:0 classid 1:1 htb rate 100mbit

tc class add dev eth1 parent 1:1 classid 1:10 htb rate 100kbit ceil 300kbit prio 0   # DNS / ACK / SYN / FIN 
tc class add dev eth1 parent 1:1 classid 1:20 htb rate 500kbit ceil 500kbit prio 1   # E-mail
tc class add dev eth1 parent 1:1 classid 1:30 htb rate 300kbit ceil 500kbit prio 2   # FTP
tc class add dev eth1 parent 1:1 classid 1:40 htb rate 300kbit ceil 500kbit prio 3   # Geral
Na classe 1:20, a opção ceil 500kbit poderia ter sido omitida, uma vez que tal ceil possui o mesmo valor de rate.

.


A instalação do comando tc e da disciplina HTB no Debian GNU/Linux

Para instalar o tc e o HTB no Debian, execute:

# apt-get install iproute


A associação do HTB com o Iptables

A divisão do tráfego pelas classes poderá ser feito com o auxílio do Iptables, utilizando a tabela mangle e o alvo CLASSIFY. A seguir, um exemplo de script de configuração do Iptables:

#!/bin/bash

PATH=/bin:/sbin:/usr/bin:/usr/sbin

iptables -t mangle -F

# portas e-mail (entrada e saida)

iptables -t mangle -A FORWARD -p tcp -m multiport --ports 25,110,995 -j CLASSIFY --set-class 1:20

# trafego HTTP entrando

iptables -t mangle -A FORWARD -o eth0 -p tcp --sport 80 -j CLASSIFY --set-class 1:30

# trafego FTP saindo (upload)

iptables -t mangle -A FORWARD -o eth1 -p tcp --dport 20 -j CLASSIFY --set-class 1:30
# DNS e ACK/SYN/FIN (pacotes com até 60 bytes)

iptables -t mangle -A FORWARD -p udp -m multiport --ports 53 -j CLASSIFY --set-class 1:10  # DNS
iptables -t mangle -A FORWARD -m length --length 0:60 -j CLASSIFY --set-class 1:10         # Flags TCP
Note que nas classes 1:30, em virtude das opções -o eth0 e -o eth1, a interface eth0 será acionada somente para o tráfego HTTP que entra e a interface eth1 somente para o tráfego FTP que sai (porta 20 - dados).


A ordem das regras

Diferentemente das tabelas filter e nat, a tabela mangle lê todas as regras, até o final, mesmo que uma delas case com a situação do pacote em tráfego. Assim, deveremos colocar casos mais específicos como últimas regras.

Observe o exemplo a seguir:

# iptables -t mangle -A FORWARD -d 10.0.0.1 -p tcp --sport 110 -j CLASSIFY --set-class 1:65
# iptables -t mangle -A FORWARD -d 10.0.0.0/8 -p tcp --sport 110 -j CLASSIFY --set-class 1:70

A idéia das regras anteriores foi limitar a leitura de e-mails (protocolo POP3). A máquina 10.0.0.1 vai utilizar a classe 1:65, enquanto que o resto da rede 10.0.0.0 vai ser enquadrada na classe 1:70. No entanto, na prática, isso não irá acontecer, uma vez que a tabela mangle lê todas as regras existentes até o final. Assim, um pacote oriundo da máquina 10.0.0.1 será enquadrado pela primeira regra e, em seguida, pela segunda. Então, valerá a última situação. Ou seja, a ordem correta das regras deverá ser a seguinte:

# iptables -t mangle -A FORWARD -d 10.0.0.0/8 -p tcp --sport 110 -j CLASSIFY --set-class 1:70
# iptables -t mangle -A FORWARD -d 10.0.0.1 -p tcp --sport 110 -j CLASSIFY --set-class 1:65


Tráfego local

Como já foi dito, o controle de tráfego deverá ser feito no momento da saída do pacote pela placa de rede. Assim, caso você tenha que controlar o tráfego gerado pela máquina que contém o HTB, deverá ser utilizada a chain OUTPUT do Iptables. Isso será útil se, por exemplo, você quiser liberar totalmente o acesso à máquina de controle. Se você não fizer isso, um ssh para tal máquina, por exemplo, será impraticável. A seguir, um exemplo de liberação do tráfego:

# tc class add dev eth0 parent 1:1 classid 1:90 htb rate 100mbit prio 0

# iptables -t mangle -A OUTPUT -j CLASSIFY --set-class 1:90


Verificando as qdiscs e as classes existentes

Para verificar as qdiscs e as classes configuradas na eth0, execute:

# tc qdisc show dev eth0
# tc class show dev eth0

Caso deseje ver também detalhes e estatísticas, acresça as chaves -d e -s, da seguinte forma:

# tc -d -s qdisc show dev eth0
# tc -d -s class show dev eth0


O módulo multiport do Iptables

O módulo multiport do Iptables é um excelente elemento para ser utilizado em controle de tráfego, uma vez que é muito flexível. Observe as regras a seguir:

# iptables -t mangle -A FORWARD -p tcp --sport 110 -j CLASSIFY --set-class 1:78
# iptables -t mangle -A FORWARD -p tcp --sport 995 -j CLASSIFY --set-class 1:78

Essas regras poderiam ser substituídas por:

# iptables -t mangle -A FORWARD -p tcp -m multiport --sport 110,995 -j CLASSIFY --set-class 1:78

Ainda, observe:

# iptables -t mangle -A FORWARD -p tcp --sport 110 -j CLASSIFY --set-class 1:78
# iptables -t mangle -A FORWARD -p tcp --sport 995 -j CLASSIFY --set-class 1:78

# iptables -t mangle -A FORWARD -p tcp --dport 25 -j CLASSIFY --set-class 1:78
# iptables -t mangle -A FORWARD -p tcp --dport 465 -j CLASSIFY --set-class 1:78

Essas regras poderiam ser substituídas por:

# iptables -t mangle -A FORWARD -p tcp -m multiport --port 25,110,465,995 -j CLASSIFY --set-class 1:78

Outros módulos poderão ser úteis. Para aprender mais sobre eles, utilize o comando:

# man iptables


As somas das velocidades das classes

As somas das velocidades das classes não necessariamente precisarão ser menores do que a velocidade máxima do link. Apenas como exemplo, admita um link Internet de 1 Mb/s. Você poderá trabalhar com as seguintes classes e prioridades:


Observando a figura anterior, podemos notar que a soma das velocidades é 1150 Kb/s, enquanto o link total é 1000 Kb/s. No entanto, como trabalhamos com prioridades, haverá uma tendência das classes com menos prioridade diminuírem as suas velocidades, proporcionalmente, quando o link estiver saturado, para que as classes com mais prioridade possam trafegar. Entretanto, em virtude das velocidades utilizadas, em caso de saturação do link, nenhuma das classes deverá parar.

Observe que não há uma necessidade de seguir uma ordem crescente numérica regular para numerar as classes e as prioridades. O mais importante é fazer a correta ligação com os pais.


Pense nisto...

Observe a figura a seguir e deixe a sua imaginação fluir...


Agora, imagine a possibilidade de ramificar a classe 1:50 em mais duas ou três classes...

Delay pool

Delay pool é um recurso do proxy Squid que permite controlar a velocidade de download por usuário. É um recurso complementar ao HTB e quase que obrigatório.

Assim sendo, veja mais sobre o assunto no artigo Implementação de delay pool com Squid.

Veja também


Links externos


Extra:


Comentários, sugestões e controle de acessos

Por favor, deixe os seus comentários e sugestões sobre este artigo no meu Blog Técnico. Para isto, clique aqui.


<absHTML>

<a href="http://www3.clustrmaps.com/counter/maps.php?url=http://www.eriberto.pro.br/wiki/index.php?title=htb" id="clustrMapsLink"><img src="http://www3.clustrmaps.com/counter/index2.php?url=http://www.eriberto.pro.br/wiki/index.php?title=htb" />

</a>


Consulte também o contador abaixo, iniciado em 19 set. 07, além do gráfico acima.

</absHTML>