terça-feira, 18 de março de 2008

Controlando a banda do tráfego P2P com Layer7 - Versão 2008

Como sempre, o principal vilão hoje de qualquer Administrador de Redes, Provedores e outros são os programas P2P, e clientes que reclamam que não tem a banda total garantida devido aos medidores de tráfego do tipo RJNET entre outros.

Aqui então vamos nós para uma aventura de marcação de pacotes e priorização dos mesmos, juntamente com a integração da marcação destes pacotes com o TC ( Traffic Control ) do GNU/Linux.

O sistema foi testado em um Debian GNU/Linux, com kernel 2.6.22.15, iptables versão 1.3.8, patch-o-matic, layer7 versão 2.17, protocolos versão 2008-02-10, imq para o kernel.

Não vou entrar nos detalhes de como compilar kernel, iptables entre outros, vamos por a mão na massa.

Primeiro, redirecionamos o trafego de download e upload para as interfaces virtuais:

iptables -v -t mangle -A PREROUTING -m comment --comment "Trafego Upload" -i eth+ -j IMQ --todev 0
iptables -v -t mangle -A POSTROUTING -m comment --comment "Trafego Download" -o eth+ -j IMQ --todev 1

usamos o eth+ por termos várias interfaces de rede.

Logo após, criamos a CHAIN chamada P2P e adicionamos o que queremos

iptables -t mangle -N P2P
iptables -t mangle -A P2P -m layer7 --l7proto ares -j MARK --set-mark 0x7
iptables -t mangle -A P2P -m layer7 --l7proto ares -j CLASSIFY --set-class 1:7
iptables -t mangle -A P2P -m layer7 --l7proto ares -j RETURN

iptables -t mangle -A P2P -m layer7 --l7proto edonkey -j MARK --set-mark 0x7
iptables -t mangle -A P2P -m layer7 --l7proto edonkey -j CLASSIFY --set-class 1:7
iptables -t mangle -A P2P -m layer7 --l7proto edonkey -j RETURN

iptables -t mangle -A P2P -m layer7 --l7proto bittorrent -j MARK --set-mark 0x7
iptables -t mangle -A P2P -m layer7 --l7proto bittorrent -j CLASSIFY --set-class 1:7
iptables -t mangle -A P2P -m layer7 --l7proto bittorrent -j RETURN

iptables -t mangle -A FORWARD -j P2P
iptables -t mangle -A POSTROUTING -j P2P

Criamos a chain P2P e adicionamos nela a marcação de pacotes e setando a classe para o qual vai ser direcionado o P2P ares, edonkey e bittorrent. O Return funciona para caso ele encontre algo antes, tipo, alguem usando ares, ele nao desça ate o final da chain procurando mais coisas.

Após marcar e setar a classe, vamos criar as classes usando o TC

ip link set dev imq0 up
ip link set dev imq1 up

tc qdisc add dev imq0 root handle 1: htb default 1
tc qdisc add dev imq1 root handle 1: htb default 1

tc class add dev imq0 parent 1: classid 1:1 htb rate 100Mbit
tc class add dev imq1 parent 1: classid 1:1 htb rate 100Mbit

#P2P
tc class add dev imq0 parent 1:1 classid 1:7 htb rate 512kbit prio 7
tc class add dev imq1 parent 1:1 classid 1:7 htb rate 512kbit prio 7

# Aqui setamos a classe do P2P 1:7 para 512kbit com a prioridade 7

Logo após, adicionamos o filtro à classe

tc filter add dev imq0 parent 1: prio 7 protocol ip handle 7 fw flowid 1:7
tc filter add dev imq1 parent 1: prio 7 protocol ip handle 7 fw flowid 1:7

Ou seja, estamos agora controlando a banda de trafego P2P.

Vamos agora adicionar um "feature" a essas regras. Marcando por ex.: tudo que vai para rjnet.com.br sair com a banda de 2mbit.

iptables -t mangle -N WEB
iptables -t mangle -A WEB -m string --algo bm --string "rjnet.com.br" -j MARK --set-mark 0x6
iptables -t mangle -A WEB -m string --algo bm --string "rjnet.com.br" -j CLASSIFY --set-class 1:6
iptables -t mangle -A WEB -j CONNMARK --save-mark

iptables -t mangle -A FORWARD -j WEB
iptables -t mangle -A POSTROUTING -j WEB

tc class add dev imq0 parent 1:1 classid 1:6 htb rate 2048kbit prio 0
tc class add dev imq1 parent 1:1 classid 1:6 htb rate 2048kbit prio 0

tc filter add dev imq0 parent 1: prio 0 protocol ip handle 6 fw flowid 1:6
tc filter add dev imq1 parent 1: prio 0 protocol ip handle 6 fw flowid 1:6
tc filter add dev imq1 parent 1: protocol ip match ip dst 200.159.128.189 flowid 1:6

Sendo assim, teremos marcado tudo que conter rjnet.com.br com uma banda de 2mbit.

Esse cenário foi montado em testes e esta funcionando normalmente.

Abraços!