IPTABLES: tasa límite de una IP entrante específica

103

No deseo limitar la tarifa de un servicio específico. Mi objetivo es limitar la tasa basada únicamente en la dirección IP entrante. Por ejemplo, usando una pseudo-regla:

john.domain.local (192.168.1.100) can only download from our httpd/ftp servers at "10KB/s" (instead of 1MB/s)

¿Cómo podría calificar el límite usando IPTables en función de las direcciones IP entrantes?

James
fuente

Respuestas:

165

IPTables no está hecho para este tipo de trabajo, donde se necesitan analizar muchos paquetes para tomar estas decisiones. ¡IPTables es en parte la respuesta!

La verdadera respuesta a esto es las increíbles y poco utilizadas instalaciones de control de tráfico en Linux. ¡Tenga en cuenta que jugar con esto sin saber lo que está sucediendo puede llevarlo a perder la conectividad de red a la máquina! ¡Usted ha sido advertido!

Suponiendo que eth0 es el dispositivo saliente, necesitará crear una cola de control de tráfico basada en clases que, de forma predeterminada, generará la mayor parte del tráfico a través de la cola 'rápida' y colocará una lista específica de personas en la cola 'lenta'.

Lo bueno de esto es que puede crear una situación en la que permita mucho tráfico saliente para el usuario lento a menos que una clase superior quiera el ancho de banda, pero este ejemplo no lo hace (siempre proporcionará 10 kbps a los usuarios lentos). El sistema de colas se verá así:

                         Inbound traffic
                              +
                              |
                              |
                              v
                     +------------------+
                     |   Class 1:1      |
                     |------------------|
                     |  Root (all flows)|
                     |       100mbit    |
                     +-----+-----+------+
                           |     |
                           |     |
                           |     |
                           |     |
                           |     |
          +----------+     |     |     +----------+
          |    1:11  +-----+     +-----+    1:12  |
          |----------|                 |----------|
          | Default  |                 | Slow     |
          |100mb-80kb|                 |   80kb   |
          +----------+                 +----------+

Para hacer esto, primero deberá configurar la disciplina de colas en el núcleo. Lo siguiente hará esto por usted ... debe ejecutar esto como un script completo

#!/bin/bash
tc qdisc add dev eth0 parent root handle 1: hfsc default 11
tc class add dev eth0 parent 1: classid 1:1 hfsc sc rate 100mbit ul rate 100mbit
tc class add dev eth0 parent 1:1 classid 1:11 hfsc sc rate 99920kbit ul rate 100000kbit
tc class add dev eth0 parent 1:1 classid 1:12 hfsc sc rate 80kbit ul rate 80kbit

tc qdisc add dev eth0 parent 1:11 handle 11:1 pfifo
tc qdisc add dev eth0 parent 1:12 handle 12:1 pfifo

El "valor predeterminado 11" es importante ya que le dice al núcleo qué hacer con el tráfico no clasificado.

Una vez hecho esto, puede configurar una regla de iptables para clasificar los paquetes que coinciden con ciertos criterios. Si planea poner a mucha gente en esta regla lenta, una regla de ipset es más apropiada (creo que debería estar disponible en rhel6).

Entonces, cree una base de datos ipset para hacer la comparación contra ...

ipset create slowips hash:ip,port

Luego cree la regla de iptables para hacer el partido.

iptables -t mangle -I OUTPUT -m set --match-set slowips dst,src -j CLASSIFY --set-class 1:12

Esto le indica al núcleo que si hace coincidir la IP de destino con el puerto de origen del conjunto, clasifíquelo en la cola lenta que configura con el control de tráfico.

Ahora, finalmente, cuando quiera reducir la velocidad de una IP, puede usar el comando ipset para agregar la ip al conjunto de la siguiente manera:

ipset add slowips 192.168.1.1,80
ipset add slowips 192.168.1.1,21
...

Puede probar que funciona con el comando "tc -s class show dev eth0" y verá estadísticas que indican que los paquetes se redirigen a la cola lenta.

Tenga en cuenta que el único inconveniente real de esto es hacerlo sobrevivir a los reinicios. No creo que haya secuencias de comandos de inicio disponibles para crear los conjuntos de ip desde los volcados al reiniciar (y también deben crearse antes de las reglas de iptables) y estoy seguro de que no hay secuencias de comandos de inicio para restablecer las reglas de control de tráfico al reiniciar. Si no te molesta, puedes recrear todo esto invocando un script en rc.local.

Matthew Ife
fuente
3
Bueno, no puedo agradecerte lo suficiente. Esto es muy descriptivo y muy informativo. Más tarde me di cuenta de que se requeriría conocimiento de CT y desde entonces he comenzado a investigar esto. ¡Gracias de nuevo!
James
Ah, y en cuanto a perder la conexión. Me estoy asegurando de tener la configuración baja antes de pasar de mi VPS a la máquina host. Además, tengo acceso VPN a la red privada en ETH0. Solo trabajaré en ETH1, así que en teoría no tendré el problema. Pero advertencia escuchada!
James
2
No puedo decir cuántas veces he leído tutoriales similares, este es el primero que tiene sentido
RC1140
55
Como nota al margen, generalmente es más apropiado hacer una limitación de recursos como esta en los grupos de control (de nuevo, también es posible y también subutilizado e impresionante), ya que puede definir límites por aplicación en CPU, memoria, E / S y red en un almacén de políticas centralizado '. Pero aún no he visto que se haga una pregunta para ofrecer una respuesta.
Matthew Ife
2
Si no le gusta la tcsintaxis, puede probar tcng que agrega un lenguaje un poco más fácil de usar que genera tccomandos. He utilizado a como este en los scripts: echo '... multi line tcng configuration ...' | tcng | sh.
Mattias Wadman
5

Es tan simple como tomar una regla de limitación de velocidad y agregar el -sinterruptor. El -sconmutador coincide con las IP entrantes. Por ejemplo, iptables -A INPUT -s 1.1.1.1y luego terminar con su método preferido de limitación de velocidad para esa regla.

Wesley
fuente
Gracias por tu pronta respuesta. Lamentablemente, mi principal problema es la segunda mitad. He investigado --limit y no he visto nada que me permita limitar en función de KB / s - ¿alguna dirección que me pueda indicar?
James
1
@ James Hubiera contactado contigo pero tuve que ir a la casa de un amigo. Acabo de regresar y veo que MIfe ha hecho un buen trabajo. =)
Wesley