Distribuir el ancho de banda usando Iproute

Este script pretende optimizar el ancho de banda de tal manera que el uso de programas p2p o envíos masivos de datos no afecten el rendimiento de nuestra conexión.

Qué hace el script

  1. Disminuye el ancho de banda para que las colas de paquetes se creen en nuestro Linux y no en el módem, que tiene colas más cortas. Con esto evitaremos laguearnos cuando haya tráfico abundante. El script esta pensado para una conexion DSL 512/128. Si se tuviera otra conexión se deberia modificar el valor de la variable ‘CAPACIDAD’ y poner el valor del ancho de banda de subida de la conexion que se tenga. 
  2. Crea 3 colas en las que distribuye el tráfico: 
    • A la primera cola (1:10) se dirige el tráfico interactivo e importante: paquetes icmp, paquetes tcp syn (de establecimiento de conexión), paquetes tcp con el TOS a Minimum-delay (son los paquetes de tráfico interactivo), y los paquetes ACK (confirmaciones) que no contienen datos. 
    • A la segunda cola (1:20) se dirige el tráfico normal. Tiene un poco menos de ancho de banda que la primera pero esto no supone problema, ya que las 3 colas están diseñadas para poder “coger prestado” ancho de banda de las demás si estas disponen de él. 
    • A la tercera cola (1:30), la menos prioritaria, dirigimos el tráfico p2p. Nuevamente puede “robar” ancho de banda de las demás, pero si hay paquetes en las otras colas, esas iran antes. Así nos aseguramos de poder usar programas p2p sin que interfieran en nuestras trnsferencias normales.

Cómo adaptarlo a nuestras necesidades

Para adaptarlo a nuestras necesidades sólamente hay que añadir las reglas de filtrado necesarias para identificar el tipo de tráfico que queramos y luego añadir la regla para colocarlo en una de las tres colas.

Veámoslo con un ejemplo que encontraremos en el script. La línea:

iptables -t mangle -A OUTPUT -p icmp -j MARK --set-mark 1

Marca con el valor ‘1’ el tráfico ICMP; ahora veamos como lo dirigimos a la primera cola:

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

Esto lo que nos dice es: los paquetes que tengan la marca ‘1’ (handle 1 fw) dirigelos a la cola 1:10 (classid 1:10). El parámetro “prio 1” es para indicar la prioridad del filtro. Se puede ver en el script que hay 2 filtros. Con el prio establecemos el orden y prioridad de los filtros. El resto de la linea lo dejaremos tal cual.

En resumen, que para encolar el tráfico en la cola que se quiera hay que añadir una línea para marcar el paquete, y otra para dirigir el paquete con esa marca a la cola que se quiera.

Sobre el trafico p2p

Este script de momento solo dirige a la tercera cola el trafico p2p generado por los procesos amule y eDonkey2000. Para añadir otro trafico p2p, se puede copiar la linea que corresponde a amule cambiando el nombre del proceso. Se puede dejar la misma marca que la de amule (3) y ya se dirigirá todo el trafico generado por ese proceso a la tercera cola.

¿Y WonderShaper?

Lo sé, hay scripts como wondershaper que realizan también esta tarea. Simplemente éste es el script que yo me he montado y que me funciona perfectamente bien. Quizá sea también más efectivo parchear el kernel con parches cono ipp2p y demás, pero para el tipo de clasificación que necesitaba me era suficiente clasificar según el proceso.

Script:

#!/bin/bash

# Colocar en esta variable la capacidad de subida de la linea
CAPACIDAD=128

# Calculamos que dejaremos como maximo un 80% de la capacidad para que no se creen
# colas en el modem y tenerlas en nuestro Linux. También calculamos un ancho de banda
# inferior para las colas menos prioritarias.

MAX=$[$CAPACIDAD*80/100]
MIN=$[$MAX-20]

### 1) Borramos las colas y las reglas de marcado ###

tc qdisc del dev eth0 root 2>/dev/null
iptables -t mangle -F

### 2) Definicion de las colas ###

echo "Creando disciplinas de cola y clases..."

# Creamos una cola padre HTB
tc qdisc add dev eth0 root handle 1: htb default 20

# Creamos una clase padre para que pueda repartir el ancho de banda sobrante entre colas
tc class add dev eth0 parent 1: classid 1:1 htb rate ${MAX}kbit ceil ${MAX}kbit

# Creamos las clases en las que clasificaremos los paquetes. A cada una le asignamos
# el ancho de banda que creamos conveniente. La primera clase es para el trafico
# interactivo, la segunda para trafico normal y la tercera para trafico p2p.
tc class add dev eth0 parent 1:1 classid 1:10 htb rate ${MAX}kbit ceil ${MAX}kbit prio 1
tc class add dev eth0 parent 1:1 classid 1:20 htb rate ${MIN}kbit ceil ${MAX}kbit prio 2
tc class add dev eth0 parent 1:1 classid 1:30 htb rate ${MIN}kbit ceil ${MAX}kbit prio 3

# Añadimos politicas de cola SQF a las clases hoja para hacerlas mas equitativas
tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10

### 3) Creacion de los filtros ###

echo "Creando clasificadores..."

# Dirigimos el trafico marcado con iptables a la clase adecuada
tc filter add dev eth0 parent 1: protocol ip prio 1 handle 1 fw classid 1:10
tc filter add dev eth0 parent 1: protocol ip prio 2 handle 3 fw classid 1:30

# El trafico no marcado (trafico normal) ira a la clase por defecto (la 1:20)

### 4) Marcado de paquetes con iptables ###

echo "Creando reglas de marcado iptables..."

# Marcamos los paquetes con iptables para que sean dirigidos a las colas pertinentes
iptables -t mangle -A OUTPUT -p tcp --tcp-flags ACK ACK 
    -m length --length 0:64 -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -m tos --tos Minimize-Delay -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -p icmp -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -p tcp --syn -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -m owner --cmd-owner 'amule' -j MARK --set-mark 3
iptables -t mangle -A OUTPUT -m owner --cmd-owner 'eDonkey2000' -j MARK --set-mark 3

Elaborado por Nacx para ADSLAyuda.com