sábado, 31 de agosto de 2013

Calidad de servicio fácil en Linux.

HowTo: QoS, Calidad de servicio fácil en Linux.

Ayer leyendo Un Sanjuanino en Rio Cuarto me dí con una entrada mencionando un vínculo a HowtoForge donde se plantea la alternativa mas facil que he visto hasta ahora para tener una implementación de QoS (por Quality of service en inglés: calidad de servicio) que aunque rudimentaria es totalmente funcional.
Se puede extender a cualquier otra disciplina de encolado y mejorar en función de las necesidades de cada uno, así que vamos a los bifes.

Requisitos necesarios:

  • Kernel con soporte para iptables.
  • Iptables instalado.
  • El comando tc instalado, que es parte del paquete iproute2
  • Opcional, l7filter para iptables.
Cualquier distribución orientada a servidor/router o redes en general ya trae estos tres requisitos preinstalados y configurados. En caso de no ser así basta con usar el gestor de paquetes de cabecera para instalar iproute2 e iptables, y seguir cualquier guía de configuración del kernel para darle soporte a iptables.

Esquematizando un poco:

El esquema de mi red es exactamente el mismo del ejemplo de howtoforge:
[internet]<–>[cablemodem]<–>[eth1  linux  eth0]<–>[red local]
Queda en cada uno adaptar las siguientes instrucciones para la topología de su red.

Implementación:

Todos los paquetes en su cabecera pueden contener o no el bit indicador de tipo de servicio (de ahora en mas ToS por Type of Service en inglés). Hay en total cuatro tipos de servicio que se pueden combinar entre sí en la práctica (aun que no debería hacerse en la teoría):
  • 0×02: Minimize Monetary Cost | Minimizar costo monetario
  • 0×04: Maximize Reliability | Maximizar fiabilidad
  • 0×08: Maximize Throughput | Maximizar tasa de transferencia
  • 0×10: Minimize Delay | Minimizar latencia
De la combinación de estos cuatro ítems surge un total de 16 combinaciones de ToS posibles, en hexadecimal:
  1. 0×00: No se especifica el bit ToS
  2. 0×02: Mimimize Monetary Cost (MMC)
  3. 0×04: Maximize Reliability (MR)
  4. 0×06: MMC + MR
  5. 0×08: Maximize Throughput (MT)
  6. 0x0a: MT + MMC
  7. 0x0c: MT + MR
  8. 0x0e: MT + MR + MMC
  9. 0×10: Minimize Delay (MD)
  10. 0×12: MD + MMC
  11. 0×14: MD + MR
  12. 0×16: MD + MMC + MR
  13. 0×18: MD + MT
  14. 0x1a: MD + MT + MMC
  15. 0x1c: MD + MT + MR
  16. 0x1e: MD + MT + MR + MMC
Que obviamente no es necesario recordar, pero que viene bien para entender mejor la sintaxis del comando tc mas adelante.

Creación de la disciplina de encolado raíz (qdisc root):

tc qdisc add dev eth1 root handle 1: prio priomap 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 0
La disciplina de encolado prio crea por defecto 3 colas, numeradas del cero al dos.
Priomap está enviando todo el tráfico que tenga activado los bits ToS de las primeras ocho combinaciones posibles -desde 0×00 hasta 0x0e- a la tercera cola (cola número 2) y  las siguientes siete combinaciones -desde 0×010 hasta 0x1c- en la segunda cola (cola número 1).
Todo el tráfico que tenga el bit ToS marcado como 0x1e irá a parar a la primera cola, la cero.
Hasta que no se vacía la primera cola, no se le da paso a la segunda cola, y hasta que no se vacía esta última no se le da paso a la tercera cola.
El howto a continuación agrega stochastic fairness queueing -que encabeza el top-ten de las cosas complicadas que he memorizado en mi vida- a cada una de las colas prio para que estas tengan además una disciplina de encolado por si misma:
tc qdisc add dev eth1 parent 1:1 handle 10: sfq
tc qdisc add dev eth1 parent 1:2 handle 20: sfq
tc qdisc add dev eth1 parent 1:3 handle 30: sfq perturb 10
Como la tercera cola es la que alojará todo el tráfico sin clasificar, se reconfigura el hash cada 10 segundos usando perturb 10. Con suerte, todo el tráfico p2p saltador de puertos -que hace las delicias del administrador de red promedio- irá a parar a esta cola.
Solo resta comenzar a clasificar el tráfico de alguna forma para que los servicios mas interactivos (SSH, World of Warcraft, Counter Strike, VoIP, etc…) vayan por la primera cola, el resto del tráfico “no-tan-importante” por la segunda cola, y todo el tráfico “bulk”, p2p y demás porquerías por la tercera cola.
Esto se puede conseguir de dos formas, con tc o con iptables.

Usando tc para clasificar el tráfico:

Ejemplo 1: Todo el tráfico que tenga como origen o destino el puerto 22 (SSH), por la primera cola:
tc filter add dev eth1 protocol ip parent 1: prio 1 u32 match ip dport 22 0xffff flowid 1:1
tc filter add dev eth1 protocol ip parent 1: prio 1 u32 match ip sport 22 0xffff flowid 1:1
Y todo lo que tenga como origen el puerto 80 (HTTP), por la segunda cola:
tc filter add dev eth1 protocol ip parent 1: prio 1 u32 match ip sport 80 0xffff flowid 1:2
Ejemplo 2: Todo el tráfico que genera el host 192.168.0.150 por la primera cola:
tc filter add dev eth1 protocol ip parent 1: prio 1 u32 match ip src 192.168.0.150 flowid 1:1
tc filter add dev eth1 protocol ip parent 1: prio 1 u32 match ip dst 192.168.0.150 flowid 1:1
Y así sucesivamente, por número de IP o por número de puerto, adaptándolo a sus necesidades.

Marcando el bit ToS con iptables:

La otra posibilidad es usar iptables dentro de la tabla mangle para modificar los paquetes al vuelo, habilitándole a cada uno el bit ToS correspondiente según sus necesidades.
Ejemplo 1: Tráfico SSH, por la primera cola se ha dicho! (marcado como 0x1e)
iptables -t mangle -A PREROUTING -p tcp –dport ssh -j TOS –set-tos 0x1e
iptables -t mangle -A PREROUTING -p tcp –sport ssh -j TOS –set-tos 0x1e
¿Descargas de rapidshare? A la segunda cola!:
iptables -t mangle -A PREROUTING -p tcp -sport 80 -j TOS –set-tos 0×10
Por supuesto que estos son solo ejemplos, habrá quien prefiera dejar HTTP para el final y priorizar otros servicios…
Ejemplo 2: El tráfico que genera 192.168.0.150 a la primera cola:
iptables -t mangle -A PREROUTING -s 192.168.0.150 -j TOS –set-tos 0×010
Frutillita del postre o ejemplo 3: Teniendo instalado l7filter se pueden hacer cosas como esta, indistintamente del número de puerto o número de IP:
iptables -t mangle -A PREROUTING -m layer7 –l7proto edonkey -j TOS –set-tos 0×02
Y asegurarnos de esta forma de que emule, edonkey, mldonkey y cuanto otro clon exista en nuestra red, vayan siempre por la tercera cola, por tener seteado el bit 0×02.
O este otro:
iptables -t mangle -A PREROUTING -m layer7 –l7proto worldofwarcraft -j TOS –set-tos 0x1e
Para asegurarnos la mas baja latencia -el menor ping, como dicen los gamers- posible en el juego en cuestión.
Para ver la lista de protocolos soportados por l7filter, visitar la página web del proyecto.
Cualquier duda, sugerencia, correción, critica destructiva, etc, no duden en comentar.

No hay comentarios:

Publicar un comentario