quarta-feira, 11 de junho de 2008

Controle de banda com TC e IPTABLES

Olá amiguinhos,

Atendendo a pedidos ontem no laboratório, vou fazer um tutorial explicando como controlar a banda usando o tc e o iptables. Vou tentar ser o mais didático possível. Bom, vamos lá, considerando que sua distribuição seja Debian, verifique se o iproute e o tcng estão instalados, caso não estejam, instale com o seguinte comando:

# aptitude install tcng


Agora vá até um diretório qualquer, e crie um script:

# vim fw


Agora monte a seguinte estrutura:

#!/bin/bash

# Linha 1
tc qd del dev eth0 root

# Linha 2
tc qd add dev eth0 root handle 1: htb

# Linha 3
tc cl add dev eth0 parent 1: classid 1:1 htb rate 4Mbit ceil 4Mbit

# Linha 4
tc cl add dev eth0 parent 1:1 classid 1:10 htb \
rate 64Kbit ceil 128Kbit prio 1

# Linha 5
tc filter add dev eth0 parent 1:0 protocol ip prio 1 \
handle 0x1 fw classid 1:10

# Linha 6
iptables -t mangle -F

# Linha 7
iptables -t mangle -A POSTROUTING -p tcp --sport 80 \
-j MARK --set-mark 0x1


Bom, vamos lá vou explicar linha por linha:

# Linha 1: Esse comando apaga a classe raiz do dispositivo eth0. Ou seja, ele apaga tudo mesmo, todas as classes que estão incorporadas na classe raiz. É interessante usar esse comando quando se faz um script que você precisa reiniciar os serviços.

# Linha 2: Adiciona uma nova fila raiz, no dispositivo eth0, com o tipo de fila htb. Esse comando cria o topo da hierarquia, onde tudo vai ser incluído nele.

# Linha 3: Adiciona uma classe mãe, no dispositivo eth0, e ela é parente da classe raiz (1:), o tipo da fila dela é htb e a banda definida para essa classe é de 4Mbit. O comando ceil, é uma variação de banda, significa que se você definir, por exemplo, 1Mbit ceil 4Mbit, o minimo é 1Mbit e o máximo que pode chegar é 4Mbit. Pra simplificar é isso que significa. Agora que criamos a classe mãe, faremos os filhos dela e trabalharemos de acordo com o limite de banda definidos por ela.

# Linha 4: Cria uma classe para o dispositivo eth0, sendo que é parente da classe 1:1 (classe mãe), a identificação dela é 1:10, o tipo da fila dela é htb, e a banda definida para essa classe é de 64Kbit no minimo e 128Kbit no máximo. O parametro prio, é a prioridade, segue o mesmo conceito do TOS. Você pode criar várias classes filho, e você pode brincar com isso, por exemplo, pra http eu defino uma velocidade, pra ssh eu defino outra e assim vai. Eu posso distribuir a banda pra cada tipo de serviço.

# Linha 5: O segredo da coisa funcionar. Essa linha cria um filtro de acordo com a marcação que foi feito no pacote com o iptables. Se você marcar o pacote com o número 0x1, o htb vai pegar esse pacote e tratar conforme a classe pede. Então, cria um filtro para o dispositivo eth0, da classe raiz, sobre o protocolo ip, com prioridade número 1, com todos os pacotes que estejam marcados com o número 0x1, e redireciona para a classe com identificação 1:10 tratar a banda. Simples não?

# Linha 6: Simplesmente limpa a tabela mangle do iptables.

# Linha 7: Marca todos os pacotes que estão saindo pela porta 80 com o número 0x1, de qualquer origem pra qualquer destino, sobre o protocolo tcp.

Essas regras foram adicionadas somente no dispositivo eth0. Se seu servidor usa um modem do tipo router, vai funcionar perfeitamente. Se for um modem que conecta sobre o pppOE, então é só mudar a interface para ppp0.

Trabalhar com o TC não é dificil, basta entender o conceito de hierarquia, veja o desenho abaixo:



Bom, espero que eu consegui ajudar. Qualquer dúvida é só perguntar.

Enjoy...

13 comentários:

Cristiano - Kamikaze disse...

Olá Anderson, tenho dúvida , eu posso marcar o pacote com qualquer numero ? ou só aquele? Por que seguinte, tenho um link de 5 mb, tenho uma rede wireless na rede 20.0 e outra rede local na 2.0, queria deixar apenas 3 mb para wireless e o resto que sobrar para rede local, e outra coisa também, se estiver só 2 pessoas no wireless, quero que divida os 3mb para os dois, ficando 1,5 mb,e caso ninguem esteja usando o wireless, mandar todo o link para a rede local ,éra isso, belo howto. abraço

Anderson Clayton disse...

Olá Cristiano.

Você pode colocar qualquer número, sendo em hexadecimal ou não. Se você colocar como decimal, o iptables converte automaticamente. Esse tipo de marcação vai funcionar perfeitamente para o que você quer.

Abraços.

Cristiano - Kamikaze disse...

Essa questão, da rede 2.0, assumir todo link do 20.0,se nao estiverem ninguem usando. preciso mexer em algo de prioridade?

Anderson Clayton disse...

Sim, a prioridade tem que ser para a maior banda. Mas, essa questão de 3Mb para a rede Wireless e a velocidade ser dividida, isso é automático. Se os dois estiverem fazendo download, a velocidade será repartida entre os dois hosts que estiverem usando a Wireless. E claro, sem afetar a banda reservada da rede local.

Cristiano - Kamikaze disse...

Olá Anderson, eu novamente !!!
Vou fazer a configuração, depois te envio aqui mesmo,e você olha se estiver correto, vou comentar na configuração , para ver se eu entendi. E minhas dúvidas !!!Abraço valeu

Se quiser me add no gtalk: cristianolinux@gmail.com

Anderson Clayton disse...

Olá Cristiano. Estarei a disposição para tirar suas dúvidas.

Abraços!

Cristiano - Kamikaze disse...

Olá outra dúvida, aonde eu configuro as minhas duas redes, no TC, nas filhos, ou criou 2 classes mãe?Dizendo 3 MB para 1 rede e 2 MB para a outra. Estou definindo 7MB em 8.192Kbit ? por que 1 MB,é 1024 KB correto ? Ou posso usar KBytes no tC? ao invés de Kbit ? Abraço :)

Anderson Clayton disse...

No TC você cria as classes que você quer determinar a velocidade da banda, e depois pelo iptables, você configura qual rede vai receber a configuração do TC.

No TC você nem mexe nada com rede, faça isso no iptables.

Cristiano - Kamikaze disse...

#!/bin/bash


# Deletando regras do TC.
tc qd del dev eth0 root

# Criando a raiz mãe.
tc qd add dev eth0 root handle 1: htb

tc class add dev eth0 parent 1: classid 1:1 htb rate 40Mbit ceil 40Mbit

# Aqui eu criei duas classes parentes da classe mãe, dividindo meu link de 5MB.
# Paras as duas redes, que irei tratar no iptables. Defini 3 MB para um parente, e 2 para outro.
# E colocando como mais prioridade a rede de 2MB, senao estiverem usando os 3MB, repasse o link.


tc class add dev eth0 parent 1:1 classid 1:10 htb rate 24Mbit ceil 24Mbit prio 1

tc class add dev eth0 parent 1:1 classid 1:20 htb rate 16Mbit ceil 16Mbit prio 10


# Interagindo com a marcação dos pacotes do iptables.

tc filter add dev eth0 parent 1:0 protocol ip prio 1 handle 0x1 fw classid 1:10

tc filter add dev eth0 parent 1:0 protocol ip prio 10 handle 0x2 fw classid 1:20

# Setando Regras de Iptables.

iptables -t mangle -F

iptables -t mangle -A POSTROUTING -s 192.168.20.0/24 -p tcp --sport 80 -j MARK --set-mark 0x1

iptables -t mangle -A POSTROUTING -s 192.168.2.0/24 -p tcp --sport 80 -j MARK --set-mark 0x2


Olá Anderson, revisa pra mim ai ? E outra, minhas regras tão valendo pra upload e download? Ou tenho que setar de outra maneira, abraço

Anderson Clayton disse...

Olá Cristiano, está certo, mas você precisa revisar duas coisas. Primeiro, se seu link é de 5 MB por que está dividindo de 24 MBit e 16 MBit? Se seu link é de 5 Mbit, você tem que dividir como tal. Outra coisa, faça o controle em outras portas também, não só na 80.

Unknown disse...

Ola Anderson,

Eu implementei a sua solução e parece que esta funcionando, mas não 100%...
Claro que eu entendo pouquissimo do assunto, então lá vão minhas duvidas:
1 - aparentemente aqui não esta respeitando a taxa de download:

tc cl add dev eth0 parent 1:1 classid 1:10 htb rate 256Kbit ceil 512Kbit prio 1

Como pode ver alterei o seu exemplo para 256 e 512, mas a taxa não passa de 100... fiz algo errado ?
segue a configuração completa que coloquei:
#Controle de taxa de download
#!/bin/bash#
#Linha 1
tc qd del dev eth0 root
# Linha 2
tc qd add dev eth0 root handle 1: htb
# Linha 3
tc cl add dev eth0 parent 1: classid 1:1 htb rate 12Mbit ceil 12Mbit
# Linha 4
tc cl add dev eth0 parent 1:1 classid 1:10 htb rate 256Kbit ceil 512Kbit prio 1
# Linha 5
tc filter add dev eth0 parent 1:0 protocol ip prio 1 handle 0x1 fw classid 1:10
# Linha 6
iptables -t mangle -F
# Linha 7
iptables -t mangle -A POSTROUTING -p tcp --sport 80 -j MARK --set-mark 0x1

Outra dúvida minha é se é possível adaptar seu modelo para criar um controle por IP, ou seja taxas diferenciadas para cada computador da rede ou pelo menos duas regras diferentes e separar os computadores entre estes dois grupos.

Muito obrigado.
Um abraço e parabéns pelo ótimo artigo !

Anderson Clayton disse...

Olá.

Nossa, ultimamente o povo está interessado nesse assunto hehe. Primeiramente, a classe mae (1:) tem que ser criada com a velocidade total da sua banda. Se sua internet tem 1MB, então você deve declarar, 1Mbit, se for de 512K, tem que ser declarada 512Kbit, e assim por diante. Se o problema persistir, tente trocar no iptables POSTROUTING por OUTPUT. Eu sempre uso OUTPUT. E sobre sua outra dúvida, todo o controle de rede, você tem que fazer pelo iptables. O TC é apenas um modo de dizer para o kernel do Linux "Eu quero que você trate os pacotes dessa forma e não da forma FIFO (First In, Firt Out)". Então se você quiser tratar por rede, basta criar suas regras no iptables de acordo com o que quer.

Abraços.

Anderson Clayton disse...

Para maiores informações sobre iptables:

http://focalinux.cipsga.org.br/guia/avancado/ch-fw-iptables.htm

Para maiores informações sobre o TC:

http://www.rns-nis.co.yu/~mps/linux-tc.html