Como segmentar el ancho de banda de una red con HTB

Imagen de damage

Viendome en la curiosidad de probar HTB para segmentar el ancho de banda de mi red, he realizado este Script, el cual lo comparto con todos ustedes y espero sea de su utilidad y beneficio.

Vale recalcar que con este script pueden segmentar por IP simples, multiples, subredes o por toda la red, segmenta tanto el upload como el download.
Si tiene alguna sugerencia al mismo bienvenidos sean (realice el script en solo 2 noches osea que puede ser mejorado :cool: )

#!/bin/sh
#
# SCRIPT HTB USANDO FOR-NET-DO v0.1.1
# CREADO POR Damage el 14/12/06 8:00AM

OK="\033[1;0m [ \033[00;32mOK \033[1;0m]\033[0m"
echo -e "ANCHO DE BANDA: $OK"

### VARIABLES ###flow
WAN="0/0"
DEVWAN="eth0"
DEVLAN="eth1"
TC=/sbin/tc
IPTABLES="/sbin/iptables -t mangle"
HTB=/sbin/htb

### PUERTOS ###
PROXY_PORT="8080"
SMTP_PORT="25"
POP3_PORT="110"
FTP_PORT="20:21"

##########
# INICIO #
##########
### ---------------- FLUSH DE REGLAS ----------------- ###
$TC qdisc del dev $DEVWAN root handle 1: htb
$TC qdisc del dev $DEVLAN root handle 2: htb
$IPTABLES -F
$IPTABLES -X

### ---------------- CREANDO CLASE ROOT -------------- ###
$TC qdisc add dev $DEVWAN root handle 1: htb default 97 r2q 10
$TC qdisc add dev $DEVLAN root handle 2: htb default 98 r2q 10

### ----------------- CLASES PADRES ---------------------------------------- ###
$TC class add dev $DEVWAN parent 1: classid 1:100 htb rate 10Mbit ceil 10Mbit quantum 128000
$TC class add dev $DEVLAN parent 2: classid 2:200 htb rate 10Mbit ceil 10Mbit quantum 128000

#ICMP tienen prioridad (marcas por defecto)
$IPTABLES -A OUTPUT -p icmp -j MARK --set-mark 97
$IPTABLES -A FORWARD -p icmp -j MARK --set-mark 97
$IPTABLES -A POSTROUTING -p icmp -j MARK --set-mark 97
$IPTABLES -A PREROUTING -p icmp -j MARK --set-mark 97
$IPTABLES -A OUTPUT -p icmp -j MARK --set-mark 98
$IPTABLES -A FORWARD -p icmp -j MARK --set-mark 98
$IPTABLES -A POSTROUTING -p icmp -j MARK --set-mark 98
$IPTABLES -A PREROUTING -p icmp -j MARK --set-mark 98

### BW1 ANCHO DE BANDA PARA IP O SUBRED ESPECIFICA #####
RATE_LAN1="64kbit"
CEIL_LAN1="128kbit"
NETWORKS_BW1="10.10.10.2"
for NET in $NETWORKS_BW1; do
$IPTABLES -A PREROUTING -s $NET -d $WAN -i $DEVLAN -j MARK --set-mark 1
$IPTABLES -A FORWARD -s $WAN -d $NET -i $DEVWAN -o $DEVLAN -j MARK --set-mark 2
$IPTABLES -A OUTPUT -d $NET -p tcp --sport $PROXY_PORT -o $DEVLAN -j MARK --set-mark 2
$IPTABLES -A OUTPUT -d $NET -p tcp --sport $SMTP_PORT -o $DEVLAN -j MARK --set-mark 2
$IPTABLES -A OUTPUT -d $NET -p tcp --sport $POP3_PORT -o $DEVLAN -j MARK --set-mark 2
done
$TC class add dev $DEVWAN parent 1:100 classid 1:1 htb rate $RATE_LAN1 ceil $CEIL_LAN1 quantum 1500
$TC class add dev $DEVLAN parent 2:200 classid 2:2 htb rate $RATE_LAN1 ceil $CEIL_LAN1 quantum 1500
$TC filter add dev $DEVWAN parent 1:0 protocol ip prio 1 handle 1 fw classid 1:1
$TC filter add dev $DEVLAN parent 2:0 protocol ip prio 1 handle 2 fw classid 2:2

### BW2 ANCHO DE BANDA PARA IP O SUBRED ESPECIFICA #####
RATE_LAN2="64kbit"
CEIL_LAN2="64kbit"
NETWORKS_BW2="10.10.10.3"
for NET in $NETWORKS_BW2; do
$IPTABLES -A PREROUTING -s $NET -d $WAN -i $DEVLAN -j MARK --set-mark 3
$IPTABLES -A FORWARD -s $WAN -d $NET -i $DEVWAN -o $DEVLAN -j MARK --set-mark 4
$IPTABLES -A OUTPUT -d $NET -p tcp --sport $PROXY_PORT -o $DEVLAN -j MARK --set-mark 4
$IPTABLES -A OUTPUT -d $NET -p tcp --sport $SMTP_PORT -o $DEVLAN -j MARK --set-mark 4
$IPTABLES -A OUTPUT -d $NET -p tcp --sport $POP3_PORT -o $DEVLAN -j MARK --set-mark 4
done
$TC class add dev $DEVWAN parent 1:100 classid 1:3 htb rate $RATE_LAN2 ceil $CEIL_LAN2 quantum 1500
$TC class add dev $DEVLAN parent 2:200 classid 2:4 htb rate $RATE_LAN2 ceil $CEIL_LAN2 quantum 1500
$TC filter add dev $DEVWAN parent 1:0 protocol ip prio 1 handle 3 fw classid 1:3
$TC filter add dev $DEVLAN parent 2:0 protocol ip prio 1 handle 4 fw classid 2:4

#### ----------- LINEA DE CLASE Y FILTRO DE CLASE POR DEFECTO ------------ ####
$TC class add dev $DEVWAN parent 1:100 classid 1:97 htb rate 9Mbit ceil 9Mbit
$TC class add dev $DEVLAN parent 2:200 classid 2:98 htb rate 9Mbit ceil 9Mbit
$TC filter add dev $DEVWAN parent 1:0 protocol ip prio 1 handle 97 fw classid 1:97
$TC filter add dev $DEVLAN parent 2:0 protocol ip prio 1 handle 98 fw classid 2:98


Nota aclaratoria: El script no calcula el valor del quantum automaticamente :) (no soy mandrake el mago en bash asi que no pidan magias ni milagros jeje) por lo cual deben tener presente ésta formula:
quantum=rate*1024/8/r2q, con un quantum=1500 se soporta una ancho de banda de hasta 128Kbits si es mayor debes utilizar la formúla para calcularlo y declararlo en la clase respectiva.

Necesito dar un rate de 256Kbit y un ceil de 384Kbit, entonces aplicamos:
quantum=(256*1024)/8)/10)
quantum=3277, esto lo declaramos en la clase del grupo correspondiente por ejemplo:

$TC class add dev $DEVWAN parent 1:100 classid 1:5 htb rate 256kbit ceil 384kbit quantum 3277
$TC class add dev $DEVLAN parent 2:200 classid 2:6 htb rate 256kbit ceil 384kbit quantum 3277


Ejemplo:

Listo eso es todo por ahora, espero haber sido claro :?
Pueden adicionar tantos grupos como deseen solo deben modificar unos pocos parametros :)
VIVA el Software Libre y el Libre Conocimiento..........
*Corregido al 20/6/07@8:55AM

Comentarios

Retomando lo del htb me di

Imagen de Monkito

Retomando lo del htb me di cuenta que parece que en el script de damage hay un error.

Al ejecutar:

$TC qdisc add dev $DEVWAN root handle 1: htb default 97 r2q 10 quantum 128000
$TC qdisc add dev $DEVLAN root handle 2: htb default 98 r2q 10 quantum 128000

Nos da un error que al mismo tiempo nos muestra la solución.


tc qdisc add dev eth0 root handle 1: htb default 97 r2q 10 quantum 128000
What is "quantum"?
Usage: ... qdisc add ... htb [default N] [r2q N]
default minor id of class to which unclassified packets are sent {0}
r2q DRR quantums are computed as rate in Bps/r2q {10}
debug string of 16 numbers each 0-3 {0}

... class add ... htb rate R1 [burst B1] [mpu B] [overhead O]
[prio P] [slot S] [pslot PS]
[ceil R2] [cburst B2] [mtu MTU] [quantum Q]
rate rate allocated to this class (class can still borrow)
burst max bytes burst which can be accumulated during idle period {computed}
mpu minimum packet size used in rate computations
overhead per-packet size overhead used in rate computations
ceil definite upper class rate (no borrows) {rate}
cburst burst but for ceil {computed}
mtu max packet size we create rate map for {1600}
prio priority of leaf; lower are served first {0}
quantum how much bytes to serve from leaf at once {use r2q}

TC HTB version 3.3

Esto nos dice que para tc qdisc las únicas opciones son default, r2q y debug, y a la vez nos indica que las opciónes válidas para tc class son rate, burst, mpu, overhead, ceil cburst, mtu, prio, y quantum

Por eso lo que debemos hacer para corregir el script es mover el quantum de las líneas de qudisc a las de class así:

$TC qdisc add dev $DEVWAN root handle 1: htb default 97 r2q 10
$TC qdisc add dev $DEVLAN root handle 2: htb default 98 r2q 10

$TC class add dev $DEVWAN parent 1: classid 1:100 htb rate 10Mbit ceil 10Mbit quantum 128000
$TC class add dev $DEVLAN parent 2: classid 2:200 htb rate 10Mbit ceil 10Mbit quantum 128000

Esto se confirma ya que en el mismo script utilizamos quantum con tc class, unas líneas mas a abajo en la definición de los canales:

$TC class add dev $DEVWAN parent 1:100 classid 1:1 htb rate $RATE_LAN1 ceil $CEIL_LAN1 quantum 1500
$TC class add dev $DEVLAN parent 2:200 classid 2:2 htb rate $RATE_LAN1 ceil $CEIL_LAN1 quantum 1500

------------
counter.li.org

Cogito Ergo Sum

------------
counter.li.org

Cogito Ergo Sum

Asi es si me habia dado

Imagen de damage

Asi es si me habia dado cuente desde hace unos dìas atras, la falta de tiempo no me dejaba hacer las modificaciones, justamente ahora me encuentro haciendo los cambios respectivos, no se que paso, creo que en alguna de la ediciones lo cambie por error jeje :(,
en un par de dìas màs que pruebe el nuevo script lo subo, le etoy haciendo una pequeñas modificaciones para incluir subclases y corregir otro error màs que existe.
Mil disculpas por las molestias.

Keep The Fire Burning.....
Stryper 1988

Listo, estaremos esperando

Imagen de Monkito

Listo, estaremos esperando la próxima entrega..... sería bueno implementarlo con esfq.

Ha por cierto eso de subclases o como dicen vulgarmente clases nietas estuve tratando de hacer pero aún no funciona bien, no me balancea correctamente la carga, no se si sea por el sfq, el mismo htb o simplemente estoy haciendo algo mal.

Saludos ;)

------------
counter.li.org

Cogito Ergo Sum

------------
counter.li.org

Cogito Ergo Sum

Pero posteelo profesor! y

Imagen de damage

Pero posteelo profesor! y asi vemos como le damos soluciòn, ya sabes el dicho 2 cabezas piensan mejor que una, aca hay mas de dos esta la comunidad entera :cool:.

Keep The Fire Burning.....
Stryper 1988

Lo de las subclases es un

Imagen de Monkito

Lo de las subclases es un tema que lo estuve analizando hace algún tiempo y cómo no dio resultados positivos hice una regresión al script original ( autoría de damage ) para ver qué estaba fallando, como encontré algunos inconvenientes lo modifiqué, el que uso en la actualidad funciona de manera tolerable pero pienso que se puede optimizar más su código y repito sería bueno implementarlo con esfq.

Les dejo una copia para que lo analicen.


#!/bin/bash
#
#
#

DEVWAN=eth0
DEVLAN=eth1

TC=/sbin/tc
IPT="/sbin/iptables -t mangle"
HTB=/sbin/htb

TOTAL_BW=1M
TOTAL_QUANTUM=13108
echo ""

echo "Flush de reglas"
$IPT -F
$IPT -Z
$IPT -X
$TC qdisc del dev $DEVWAN root handle 1: htb
$TC qdisc del dev $DEVLAN root handle 2: htb

echo "Creando clases root"
$TC qdisc add dev $DEVWAN root handle 1: htb default 97 r2q 10
$TC qdisc add dev $DEVLAN root handle 2: htb default 98 r2q 10

echo "Creando clases padres"
$TC class add dev $DEVWAN parent 1: classid 1:100 htb rate "$TOTAL_BW"bit ceil "$TOTAL_BW"bit quantum $TOTAL_QUANTUM
$TC class add dev $DEVLAN parent 2: classid 2:200 htb rate "$TOTAL_BW"bit ceil "$TOTAL_BW"bit quantum $TOTAL_QUANTUM

#ICMP tienen prioridad (marcas por defecto)
#Salida por DEV_WAN
$IPT -A OUTPUT -p icmp -o $DEVWAN -j MARK --set-mark 97
$IPT -A FORWARD -p icmp -i $DEVLAN -o $DEVWAN -j MARK --set-mark 97
$IPT -A POSTROUTING -p icmp -o $DEVWAN -j MARK --set-mark 97
#Salida por DEV_LAN
$IPT -A OUTPUT -p icmp -o $DEVLAN -j MARK --set-mark 98
$IPT -A FORWARD -p icmp -i $DEVWAN -o $DEVLAN -j MARK --set-mark 98
$IPT -A POSTROUTING -p icmp -o $DEVLAN -j MARK --set-mark 98

#-----------------------------------------------------------------------------------------------------------
function mark_ip {
MWAN=$1
MLAN=$2
IP=$3
#Control paquetes de subida, salida de la DEVWAN
$IPT -A OUTPUT -s $IP -d 0/0 -p all -o $DEVWAN -j MARK --set-mark $MWAN
$IPT -A FORWARD -s $IP -d 0/0 -p all -i $DEVLAN -o $DEVWAN -j MARK --set-mark $MWAN
$IPT -A POSTROUTING -s $IP -d 0/0 -p all -o $DEVWAN -j MARK --set-mark $MWAN

#Control paquetes de bajada, salida de la DEVLAN
$IPT -A OUTPUT -d $IP -s 0/0 -p all -o $DEVLAN -j MARK --set-mark $MLAN
$IPT -A FORWARD -d $IP -s 0/0 -p all -i $DEVWAN -o $DEVLAN -j MARK --set-mark $MLAN
$IPT -A POSTROUTING -d $IP -s 0/0 -p all -o $DEVLAN -j MARK --set-mark $MLAN
}
function class_filter {
MWAN=$1
MLAN=$2
RATE=$3
CEIL=$4
QUAN=$5
$TC class add dev $DEVWAN parent 1:100 classid 1:"$MWAN" htb rate "$RATE"bit ceil "$CEIL"bit quantum $QUAN
$TC class add dev $DEVLAN parent 2:200 classid 2:"$MLAN" htb rate "$RATE"bit ceil "$CEIL"bit quantum $QUAN
$TC filter add dev $DEVWAN parent 1:0 protocol ip prio 1 handle $MWAN fw classid 1:"$MWAN"
$TC filter add dev $DEVLAN parent 2:0 protocol ip prio 1 handle $MLAN fw classid 2:"$MLAN"
}
#-----------------------------------------------------------------------------------------------------------

### CANAL 1: 256KBPS_8:1
RATE="256k"
CEIL="256k"
QUAN=3277
CPEs="10.10.10.2 10.10.10.3 10.10.10.4 10.10.10.5 10.10.10.6 10.10.10.7 10.10.10.8 10.10.10.9"
for IP in $CPEs; do
mark_ip 1 2 $IP
done
class_filter 1 2 $RATE $CEIL $QUAN

### CANAL 2: 256KBPS_4:1
RATE="256k"
CEIL="256k"
QUAN=3277
CPEs="10.10.10.10 10.10.10.11 10.10.10.12 10.10.10.13"
for IP in $CPEs; do
mark_ip 3 4 $IP
done
class_filter 3 4 $RATE $CEIL $QUAN

### CANAL 3: 512KBPS_1:1
RATE="512k"
CEIL="512k"
QUAN=6554
CPEs="10.10.10.14"
for IP in $CPEs; do
mark_ip 5 6 $IP
done
class_filter 5 6 $RATE $CEIL $QUAN

echo "Clase por defecto"
class_filter 97 98 128k 256k 3277

NOTA1: modifiqué un poco el marcado de paquetes usando mi sentido común tomando en cuenta que lo que se puede controlar es el ancho de banda de salida de las tarjetas de red, no soy experto, si tengo algún error en eso por favor hacérmelo saber.

NOTA2: eliminé las reglas de prerouting ya que pienso que cuando un paquete llega ya consumió ancho de banda y es irrelevante marcarlo, a menos que el paquete salga desde el propio servidor el cual se marca con output.

------------
counter.li.org

Cogito Ergo Sum

------------
counter.li.org

Cogito Ergo Sum

afinamiento de la segmentacion

bueno con el permiso de damage y monkito, usualmente el download y upload no son iguales, me tome el atrevimiento de agregar otros parametros para hacer el scrip mas general, un granito mas. diferencie el rate de download del upload con sus respectivos ceils, y lo probe como ven con una sola ip pero igual es generalizarlo, hay va,


#!/bin/sh -x
#
#
#

DEVWAN=eth1
DEVLAN=eth0

TC=/usr/sbin/tc
IPT="/usr/sbin/iptables -t mangle"
#HTB=/sbin/htb

TOTAL_BW=10M
TOTAL_QUANTUM=13108
echo ""

echo "Flush de reglas"
$IPT -F
$IPT -Z
$IPT -X
$TC qdisc del dev $DEVWAN root handle 1: htb
$TC qdisc del dev $DEVLAN root handle 2: htb

echo "Creando clases root"
$TC qdisc add dev $DEVWAN root handle 1: htb default 97 r2q 10
$TC qdisc add dev $DEVLAN root handle 2: htb default 98 r2q 10

echo "Creando clases padres"
$TC class add dev $DEVWAN parent 1: classid 1:100 htb rate "$TOTAL_BW"bit ceil "$TOTAL_BW"bit quantum $TOTAL_QUANTUM
$TC class add dev $DEVLAN parent 2: classid 2:200 htb rate "$TOTAL_BW"bit ceil "$TOTAL_BW"bit quantum $TOTAL_QUANTUM

#ICMP tienen prioridad (marcas por defecto)
#Salida por DEV_WAN
echo icmp por wan
$IPT -A OUTPUT -p icmp -o $DEVWAN -j MARK --set-mark 97
$IPT -A FORWARD -p icmp -i $DEVLAN -o $DEVWAN -j MARK --set-mark 97
$IPT -A POSTROUTING -p icmp -o $DEVWAN -j MARK --set-mark 97
#Salida por DEV_LAN
$IPT -A OUTPUT -p icmp -o $DEVLAN -j MARK --set-mark 98
$IPT -A FORWARD -p icmp -i $DEVWAN -o $DEVLAN -j MARK --set-mark 98
$IPT -A POSTROUTING -p icmp -o $DEVLAN -j MARK --set-mark 98

#-----------------------------------------------------------------------------------------------------------
mark_ip () {
MWAN=$1
MLAN=$2
IP=$3
#Control paquetes de subida, salida de la DEVWAN
$IPT -A OUTPUT -s $IP -d 0/0 -p all -o $DEVWAN -j MARK --set-mark $MWAN
$IPT -A FORWARD -s $IP -d 0/0 -p all -i $DEVLAN -o $DEVWAN -j MARK --set-mark $MWAN
$IPT -A POSTROUTING -s $IP -d 0/0 -p all -o $DEVWAN -j MARK --set-mark $MWAN

#Control paquetes de bajada, salida de la DEVLAN
$IPT -A OUTPUT -d $IP -s 0/0 -p all -o $DEVLAN -j MARK --set-mark $MLAN
$IPT -A FORWARD -d $IP -s 0/0 -p all -i $DEVWAN -o $DEVLAN -j MARK --set-mark $MLAN
$IPT -A POSTROUTING -d $IP -s 0/0 -p all -o $DEVLAN -j MARK --set-mark $MLAN
}
class_filter () {
MWAN=$1
MLAN=$2
DRATE=$3
DCEIL=$4
QUAN=$5
URATE=$6
UCEIL=$7
echo MWAN $MWAN
echo MLAN $MLAN
echo DRATE $DRATE
echo DCEIL $DCEIL
echo QUAN $QUAN
echo URATE $URATE
echo UCEIL $UCEIL

$TC class add dev $DEVWAN parent 1:100 classid 1:"$MWAN" htb rate "$URATE"bit ceil "$UCEIL"bit quantum $QUAN
$TC class add dev $DEVLAN parent 2:200 classid 2:"$MLAN" htb rate "$DRATE"bit ceil "$DCEIL"bit quantum $QUAN
$TC filter add dev $DEVWAN parent 1:0 protocol ip prio 1 handle $MWAN fw classid 1:"$MWAN"

$TC filter add dev $DEVLAN parent 2:0 protocol ip prio 1 handle $MLAN fw classid 2:"$MLAN"
exit 1
}
#-----------------------------------------------------------------------------------------------------------

### CANAL 1: 256KBPS_8:1
URATE="20k"
UCEIL="256k"
QUAN=3277
DRATE="100K"
DCEIL="1024k"
CPEs="192.168.3.220"
for IP in $CPEs; do
mark_ip 1 2 $IP
done
class_filter 1 2 $DRATE $DCEIL $QUAN $URATE $UCEIL
echo canal 1
### CANAL 2: 256KBPS_4:1
#RATE="256k"
#CEIL="256k"
#QUAN=3277
#CPEs="10.10.10.10 10.10.10.11 10.10.10.12 10.10.10.13"
#for IP in $CPEs; do
# mark_ip 3 4 $IP
#done
#class_filter 3 4 $RATE $CEIL $QUAN

### CANAL 3: 512KBPS_1:1
#RATE="512k"
#CEIL="512k"
#QUAN=6554
#CPEs="10.10.10.14"
#for IP in $CPEs; do
# mark_ip 5 6 $IP
#done
#class_filter 5 6 $RATE $CEIL $QUAN

echo "Clase por defecto"
class_filter 97 98 60k 1024k 3277 10k 220k

Problema con segmentacion Upstream

Imagen de micronic

Hola! damage serias tan amable de postear la regla que tenes en tu firewall para el proxy transparente? ya que si quito la regla de mi firewall (Shorewall) HTB-GEN segmenta pefectamente el ancho de banda tanto de subida como de bajada.

Esta es la regla que tengo con la que squid funciona perfectamente pero htb-gen no me segmenta la velocidad de subida:
REDIECT loc 3128 tcp 80 20/sec:5

Tambien pobe sacandole lo ultimo sin resultados:
REDIECT loc 3128 tcp 80

Claramente el problema de la segmentacion de upstream esta con la regla que colocamos en el firewall para que funcione el proxy transparente.

---------------------------------
GNU/Linux|The Future Technology|

Bueno después de batallar

Imagen de nino1511

Bueno después de batallar tanto, tratando de limitar el ancho de subida (no me limitaba ni con cbq, prometheusqos, htb, htb-gen), probe el script que público monkito (también hecho en htb) y he solucionado ese problema, yo se que el post esta en 2009 pero ni modo recién lo encuentro.

Para los que tienen ese problema de que no les limitar la subida, esta es una solución muy buena.

Nota: Aclaro esto de no limitar la subida ocurre cuando se redirecciona del puerto 80 al proxy o colocando el proxy manual, cuando no están ninguna de estas opciones anteriores la subida es controlado por todos los "limitadores" que nombre antes.

Saludos

Vamos Ecuador, si se puede

Páginas