Diferencia entre revisiones de «Entendiendo iptables hashlimit»

De Jose Castillo Aliaga
Ir a la navegación Ir a la búsqueda
Línea 45: Línea 45:
Aquí vamos a establecer un límite de 2 paquetes por minuto y un ''burst'' de 5.  
Aquí vamos a establecer un límite de 2 paquetes por minuto y un ''burst'' de 5.  
<pre class="code">
<pre class="code">
iptables -I FORWARD -m hashlimit --hashlimit-above 2/minute --hashlimit-burst 5 --hashlimit-mode srcip,dstip --hashlimit-name bwlimit -j DROP  
root@firewall:~# iptables -I FORWARD -m hashlimit --hashlimit-above 2/minute --hashlimit-burst 5 --hashlimit-mode srcip,dstip --hashlimit-name bwlimit -j DROP  
</pre>
</pre>
A continuación, desde el cliente hacemos ping a otra màquina (en el ejemplo lo hago cada 5 segundos para tener menos líneas).  
A continuación, desde el cliente hacemos ping a otra màquina (en el ejemplo lo hago cada 5 segundos para tener menos líneas).  

Revisión del 00:38 7 nov 2017

Cuando nos proponemos limitar el ancho de banda o las conexiones a o desde Internet, hay algunas opciones a tener en cuenta. De forma general, todo el mundo te recomienda leer el lartc y tienen razón. Es bastante complicado hacerlo bien y algunos han hecho herramientas como Wondershaper. Esta ha quedado obsoleta ([1]) y no funciona correctamente. Otra alternativa es echar mano de IPtables y su extensión hashlimit.

Antes de empezar, voy a suponer un caso real sobre el que voy a explicar las alternativas: Tenemos un aula con unos 25 pcs y algunos móviles conectados por Wifi. Todos pasan por un Ubuntu server que hace de router. La conexión al exterior es relativamente buena, pero si algunos alumnos usan mucho el youtube o otros servicios de streaming, comienza a ir lento. Nos proponemos limitar el ancho de banda de la forma más respetuosa posible y sin dañar a los que quieren trabajar.

Iptables tiene una extensión llamada hashlimit. Esta es parecida a otra llamada limit. La diferencia es que hashlimit directamente puede trabajar con múltiples IPs de origen y de destino y limit es para toda la tarjeta de red.

El funcionamiento es el siguiente:

  1. Hashlimit registra cada conexión entre ips de origen y de destino.
  2. Si esta supera el límite de conexiones por segundo o de velocidad, ejecuta la regla. (Posiblemente DROP)
  3. Cuando pasa un tiempo, permite de nuevo conectar, pero si se supera la velocidad, vuelve a cortar.

Aquí hay un problema: Muchas conexiones pueden ir muy rápido pero no ser muy pesadas. Podríamos estar cortando conexiones sin parar sólo por la velocidad de la red o del servidor remoto.

Para solucionar este problema, hashlimit cuenta con la opció --hashlimit-burst que permite una conexión rápida durante una cantidad máxima de datos.

Entorno de pruebas

Para probar el funcionamiento voy a usar containers LXD. Estos serian los comandos para crear un container que hace de cortafuegos y uno que se conecta a través de él a Internet:

# lxc launch ubuntu:16.04 firewall
# lxc launch ubuntu:16.04 cliente
# lxc profile create clientes
# lxc profile apply cliente clientes
# echo -e "\n\nauto switch1\niface switch1 inet static\naddress 192.168.99.1\nnetmask 255.255.255.0\nbridge-ports none" >> /etc/network/interfaces
# brctl addbr switch1
# lxc config device add cliente eth1 nic nictype=bridged parent=switch1 name=eth1
# lxc config device add firewall eth1 nic nictype=bridged parent=switch1 name=eth1
# lxc exec cliente -- bash -c 'echo -e "\n\nauto eth1\niface eth1 inet static\naddress 10.20.30.1\nnetmask 255.255.255.0\ngateway 10.20.30.254" >> /etc/network/interfaces'
# lxc exec firewall -- bash -c 'echo -e "\n\nauto eth1\niface eth1 inet static\naddress 10.20.30.254\nnetmask 255.255.255.0" >> /etc/network/interfaces'
# lxc exec cliente -- ifdown eth1
# lxc exec cliente -- ifup eth1
# lxc exec firewall -- ifdown eth1
# lxc exec firewall -- ifup eth1
# lxc exec firewall -- sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
# lxc exec firewall -- apt update
# lxc exec firewall -- iptables -A FORWARD -j ACCEPT
# lxc exec firewall -- iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# lxc exec firewall -- apt install iptables-persistent
# lxc exec firewall -- bash -c 'iptables-save > /etc/iptables/rules.v4'
# lxc exec firewall -- reboot

Ejemplos con paquetes

Aquí vamos a establecer un límite de 2 paquetes por minuto y un burst de 5.

root@firewall:~# iptables -I FORWARD -m hashlimit --hashlimit-above 2/minute --hashlimit-burst 5 --hashlimit-mode srcip,dstip --hashlimit-name bwlimit -j DROP 

A continuación, desde el cliente hacemos ping a otra màquina (en el ejemplo lo hago cada 5 segundos para tener menos líneas).

root@cliente:~# ping -O -i 5 10.182.234.51
PING 10.182.234.51 (10.182.234.51) 56(84) bytes of data.
64 bytes from 10.182.234.51: icmp_seq=1 ttl=63 time=0.124 ms
64 bytes from 10.182.234.51: icmp_seq=2 ttl=63 time=0.116 ms
64 bytes from 10.182.234.51: icmp_seq=3 ttl=63 time=0.116 ms
64 bytes from 10.182.234.51: icmp_seq=4 ttl=63 time=0.120 ms
64 bytes from 10.182.234.51: icmp_seq=5 ttl=63 time=0.104 ms
no answer yet for icmp_seq=6
64 bytes from 10.182.234.51: icmp_seq=7 ttl=63 time=0.102 ms
no answer yet for icmp_seq=8
no answer yet for icmp_seq=9
no answer yet for icmp_seq=10
no answer yet for icmp_seq=11
no answer yet for icmp_seq=12
64 bytes from 10.182.234.51: icmp_seq=13 ttl=63 time=0.116 ms

Como se puede ver, los primeros 5 pings funcionan, pero luego van fallando todos hasta que, después de un tiempo va dejando pasar otros pero no más de 2 por minuto.

Este es el fichero /proc/net/ipt_hashlimit/bwlimit

59 10.20.30.1:0->10.182.234.51:0 283648 4800000 960000
51 10.182.234.51:0->10.20.30.1:0 283648 4800000 960000
  • El primer número son los segundos que quedan hasta que la regla desaparezca. Sólo bajan si no se producen nuevas peticiones.
  • Después van las IP de origen y destino.
  • El tercer número és el crédito que queda. Si está por debajo del quinto número eliminará los paquetes que entren. Este número aumenta mientras no llegan paquetes nuevos o está eliminando los que van llegando. De esta manera, cuando llega a ser mayor que el quinto número deja pasar un paquete y se decrementa en 96000.
  • El cuarto número es el crédito máximo que se puede tener con el burst.
  • El quinto es la cantidad de crédito que se pierde cada vez que detecta un nuevo paquete. Hay un cálculo interesante que hacer aquí: 4800000/960000 = 5 (El burst)

Ejemplos con velocidad

Vamos a analizar esta regla:

# iptables -I FORWARD -m hashlimit --hashlimit-above 3000kb/s --hashlimit-burst 5mb --hashlimit-mode srcip,dstip --hashlimit-name bwlimit -j DROP

Aquí estamos permitiendo conexiones a velocidades menores de 3000kb/s. Si se detecta una descarga a más velocidad, enviará sus paquetes al DROP. Pero no corta la conexión, ya que después de un poco de tiempo, vuelve a permitirla. Se reanuda y si vuelve a esa velocidad volverá a eliminar los paquetes.

Pero si las descargas son menores a 5mb no se aplica la regla, ya que tiene un hashlimit-burst de 5mb. Esto permite que funcione correctamente en webs poco pesadas.

El funcionamiento en detalle se puede analizar observando el fichero /proc/net/ipt_hashlimit/bwlimit en él se detallan todas las conexiones detectadas. Vamos a fijarnos en esta línea. Ha aparecido mientras se descargaba un archivo de la 10.20.2.2:

45 192.168.9.100:0->10.20.2.2:0 4194304000 2 65534

El primer número es un contador de 60 segundos hacia atrás. Cuando se produce una conexión a esa velocidad se registra. Si esa conexión se acaba, el contador va hacia atrás hasta que es 0 y desaparece. Mientras existe el contador, los paquetes a más velocidad que superen el burst se eliminarán. Mientras continue la conexión y se supere el límite, el contador se refrescará a 60.

Enlaces

http://poorlydocumented.com/2017/08/understanding-iptables-hashlimit-module/

http://tlfabian.blogspot.com.es/2014/06/how-does-iptables-hashlimit-module-work.html

https://unix.stackexchange.com/questions/215903/what-do-the-fields-in-proc-net-ipt-hashlimit-file-mean