IPTABLES - Taxa limite de um IP de entrada específico

102

Eu não quero limitar a taxa de um serviço específico. Meu objetivo é limitar a taxa com base unicamente no endereço IP de entrada. Por exemplo, usando uma pseudo-regra:

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

Como eu poderia limitar o limite usando IPTables com base nos endereços IP de entrada?

    
por James 28.04.2012 / 23:09

2 respostas

165

O IPTables não é feito para este tipo de trabalho, onde muitos e muitos pacotes precisam ser analisados para tomar essas decisões. O IPTables é parcialmente a resposta!

A verdadeira resposta para isso são os recursos de controle de tráfego impressionantes e subutilizados no Linux. Observe que, sem saber o que está acontecendo, você pode perder a conectividade de rede com a máquina! Você foi avisado!

Assumindo que eth0 é o dispositivo de saída, você precisará criar uma fila de controle de tráfego baseada em classe que, por padrão, gera a maior parte do tráfego na fila "rápida" e coloca uma lista específica de pessoas na fila "lenta".

A beleza disso é que você pode criar uma situação na qual permite lotes de tráfego de saída para o usuário lento, a menos que uma classe que o substitua deseje a largura de banda, mas esse exemplo não faz isso (sempre fornecerá 10kbps aos usuários lentos). O sistema de filas será parecido com isto:

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

Para fazer isso, primeiro você precisa configurar a disciplina de enfileiramento no kernel. O seguinte irá fazer isso para você .. você deve executar isso como um script inteiro

#!/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

O "padrão 11" é importante, pois informa ao kernel o que fazer com o tráfego não classificado.

Depois disso, você pode configurar uma regra iptables para classificar pacotes que correspondam a um determinado critério. Se você planeja colocar muitas e muitas pessoas nessa regra lenta, uma regra de ipset é mais apropriada (o que deve estar disponível no rhel6 eu acredito).

Portanto, crie um banco de dados ipset para fazer a correspondência com ...

ipset create slowips hash:ip,port

Em seguida, crie a regra iptables para fazer a correspondência ...

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

Isso instrui o kernel que, se você combinar o IP de destino com a porta de origem do conjunto, classifique-o na fila lenta que você configurou com o controle de tráfego.

Agora, finalmente, sempre que você quiser desacelerar um IP, você pode usar o comando ipset para adicionar o ip ao conjunto como este:

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

Você pode testá-lo usando o comando "tc -s classe show dev eth0" e você verá estatísticas indicando que os pacotes estão sendo redirecionados para a fila lenta.

Observe que a única desvantagem real disso é fazê-lo sobreviver a reinicializações. Eu não acho que existam scripts de init disponíveis para criar os ipsets dos dumps na reinicialização (e eles também devem ser criados antes das regras do iptables) e estou certo de que não há scripts de init para redefinir o controle de tráfego regras de reinicialização. Se você não se incomodar, pode simplesmente recriar tudo ao invocar um script em rc.local.

    
por 29.04.2012 / 01:35
5

É tão simples quanto tomar uma regra de limitação de taxa e adicionar a opção -s . A opção -s corresponde aos IPs recebidos. Por exemplo, iptables -A INPUT -s 1.1.1.1 e, em seguida, terminar com seu método preferido de limitação de taxa para essa regra.

    
por 28.04.2012 / 23:12