QoS por HTB + Iptables

Fórum de Suporte

Boas.

Estou a tentar implementar um sistema de Quality-of-Service em minha casa:

http://img503.imageshack.us/img503/3470/rededobufuhjc8.jpg

O servidor está a routear internet (4096/256 kbps) para a interface eth1. A eth2 não está a ser usada de momento, será para fazer bridge com outra LAN.

A ideia é tratar o tráfego que irá sair pela eth0, vindo da eth1 e do próprio server, de modo a que o serviço de VoIP não seja afectado por P2P ou qualquer outro tipo de tráfego: http, ftp, etc. Para isso, implementei QoS com base em HTB:

#!/bin/bash

# QoS VS 1.00
# tc -s -d class show dev eth0

IF_EXTERNA=eth0
IF_INTERNA=eth1

LIMITE_UPSTREAM=224kbit
LIMITE_UPSTREAM_BT=205kbit

function start()
{
echo ""
echo "**************************************"
echo "* QoS VS 1.00 * "
echo "* Uptream = $LIMITE_UPSTREAM *"
echo "* BitTorrent = $LIMITE_UPSTREAM_BT *"
echo "**************************************"
echo ""
echo ""

# Priority marks
MARKPRIO1="0x1"
MARKPRIO2="0x2"
MARKPRIO3="0x3"
MARKPRIO4="0x4"

# Load modules
modprobe sch_htb

# Delete Queue Disciplines
tc qdisc del dev $IF_EXTERNA root 2> /dev/null > /dev/null

# Specify queue discipline
tc qdisc add dev $IF_EXTERNA root handle 1:0 htb default 30

# Create Root Class
tc class add dev $IF_EXTERNA parent 1:0 classid 1:1 htb rate $LIMITE_UPSTREAM ceil $LIMITE_UPSTREAM

# Create Sub Classes
tc class add dev $IF_EXTERNA parent 1:1 classid 1:10 htb rate 128kbit ceil $LIMITE_UPSTREAM prio 1
tc class add dev $IF_EXTERNA parent 1:1 classid 1:20 htb rate 100kbit ceil $LIMITE_UPSTREAM prio 2
tc class add dev $IF_EXTERNA parent 1:1 classid 1:30 htb rate 1kbit ceil $LIMITE_UPSTREAM_BT prio 3

# Filter packets
tc filter add dev $IF_EXTERNA parent 1:0 protocol ip prio 1 handle $MARKPRIO1 fw classid 1:10
tc filter add dev $IF_EXTERNA parent 1:0 protocol ip prio 2 handle $MARKPRIO2 fw classid 1:20
tc filter add dev $IF_EXTERNA parent 1:0 protocol ip prio 3 handle $MARKPRIO3 fw classid 1:30

# Add queuing disciplines
tc qdisc add dev $IF_EXTERNA parent 1:10 sfq perturb 10
tc qdisc add dev $IF_EXTERNA parent 1:20 sfq perturb 10
tc qdisc add dev $IF_EXTERNA parent 1:30 sfq perturb 10

echo ""
echo "STARTED!!!!!!!!!!!"
echo ""
}

function stop()
{
tc qdisc del dev $IF_EXT root 2> /dev/null > /dev/null
tc qdisc del dev $IF_INT root 2> /dev/null > /dev/null

echo ""
echo "STOPED!!!!!!!!!!!"
echo ""

}

function restart()
{
stop
start
}

case "$1" in
'start')
start
;;
'restart')
restart
;;
'stop')
stop
;;
*)
echo "usage: start|restart|stop"
esac

########################################################

MARKPRIO1="0x1"
MARKPRIO2="0x2"
MARKPRIO3="0x3"

IP_PAP2T="192.168.1.10"
P2P_PORT="53666"

IF_EXTERNA=eth0
IF_INTERNA=eth1

# Reset rules in mangle table
iptables -F -t mangle

# Setting priority marks

# Priority 1
# ICMP
iptables -t mangle -A PREROUTING -p icmp -j MARK --set-mark $MARKPRIO1

# DNS
iptables -t mangle -A PREROUTING -p tcp --dport 53 -j MARK --set-mark $MARKPRIO1

# NTP
iptables -t mangle -A PREROUTING -p tcp --dport 123 -j MARK --set-mark $MARKPRIO1

# VoIP
iptables -t mangle -A PREROUTING -s $IP_PAP2T -j MARK --set-mark $MARKPRIO1

# CS-Source
iptables -t mangle -A PREROUTING -p tcp --dport 1200 -j MARK --set-mark $MARKPRIO1
iptables -t mangle -A PREROUTING -p tcp --dport 27000:27015 -j MARK --set-mark $MARKPRIO1
iptables -t mangle -A PREROUTING -p tcp --dport 27020:27039 -j MARK --set-mark $MARKPRIO1
iptables -t mangle -A PREROUTING -p udp --dport 1200 -j MARK --set-mark $MARKPRIO1
iptables -t mangle -A PREROUTING -p udp --dport 27000:27015 -j MARK --set-mark $MARKPRIO1
iptables -t mangle -A PREROUTING -p udp --dport 27020:27039 -j MARK --set-mark $MARKPRIO1

# Non TCP
#iptables -t mangle -A PREROUTING -p ! tcp -j MARK --set-mark $MARKPRIO1

# ********************************************************************************

# Priority 2
# HTTP
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark $MARKPRIO2
iptables -t mangle -A PREROUTING -p tcp --dport 8080 -j MARK --set-mark $MARKPRIO2

# HTTPS
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark $MARKPRIO2

# Proxy
iptables -t mangle -A PREROUTING -p tcp --dport 3128 -j MARK --set-mark $MARKPRIO2

# ********************************************************************************

# Priority 3
# P2P
iptables -t mangle -A PREROUTING -p tcp --sport $P2P_PORT -j MARK --set-mark $MARKPRIO3
iptables -t mangle -A PREROUTING -p tcp --dport $P2P_PORT -j MARK --set-mark $MARKPRIO3

echo ""
echo " ******* DONE!!! ******* "
echo ""

O problema é que isto não está a funcionar bem. Se reduzir a "rate" da classe 1:30, por exemplo, para 2kbps, "deixo de ter" internet, quer no servidor, quer na restante rede. É estranho, dado que essa classe não afecta HTTP e DNS (1:20 e 1:10, respectivamente)!

A somar a isto, o serviço de VoIP apresenta lag aproximadamente de 1 segundo se, no servidor, estiver com P2P a "upar" a 25KB/s.

Agradeço ajuda. :(

[[]]

PS: Todos os IPs são atribuidos por DHCP, estando os referênciados no esquema reservados por MacAddress.

Opções de visualização dos comentários

Seleccione a sua forma preferida de visualização de comentários e clique "Gravar configuração" para activar as suas alterações.

Caro colega, apesar de não

Caro colega,
apesar de não ser especialista em QoS quero apenas deixar algumas dicas da minha pequena experiência na utilização deste tipo de scrips.

Em primeiro lugar há enormes dificuldades em controlar valores tão baixos definidos para as classes, 2kbit por exemplo. Se usarmos valores de outra ordem de grandeza, penso que iria funcionar melhor, por exemplo, teres 10 Mbit e definires 2Mbit para a classe 1:30 em vez de 2kbit. 2kbit é um valor muito baixo para poder ser gerido, é isso que quero dizer.

O lag no serviço de VOIP, não explicas se estás a usar VOIP internamente para testar ou com estás a fazer uma chamada para o exterior da tua LAN, é que se é internamente, pode ser provocado por falta de recursos na maquina a correr iptables/QoS, se é externa a chamada, pode não ter a haver com o script, uma vez que em ligações adsl "normais" que eu saiba os ISp's não dão prioridade a trafego VOIP.

Deixo-te aqui um link http://www.lartc.org/ que possivelmente já conheces mas onde está muito ( boa ) informação sobre isto.

Tenta "brincar" com a fragmentação dos pacotes mexendo nos valores do mtu das placas , que normalmente está definido para 1500. Tenta reduzir por exemplo para 1492 na tua eth0.

Cumprimentos Cordiais,
Pedro Rodrigues

Boas,

Boas,

A implementação de QoS que apresentei destina-se a tratar uma ligação à internet 4mbps/256kbps.

O serviço de VoIP na minha lan é exclusivo para a internet, não interno. Para isso tenho um adaptador ATA com um telefone normal associado.

O problema ficou resolvido adicionando uma regra para marcar pacotes de DNS em formato UDP, dando prioridade 1 e marcando do tráfego de P2P, no servidor, pela chain OUTPUT, invés da PREROUTNG.

Obrigado a todos.

A mailing list do lartc tb

A mailing list do lartc tb é muito boa e está activa com malta que sabe o que diz e não tem medo de ajudar quem insiste :)

infelizmente fui abençoado com um packeteer e acabei por nunca mais mexer em QOS em linux, mas quem sabe um dia destes dê tb um giro nessas andanças :D

até lá!

::-------------------------------------
"Manage complexity, achieve agility"