Traffic Shaping in Linux

Published by Lello on

Consideriamo una LAN su cui è installato un proxy server; questo server è collegato (tramite firewall) ad internet con una banda di 8Mbps (una bella sHDSL). Se non mettiamo dei freni all’utilizzo di banda da parte del proxy server, può capitare che tale servizio monopolizzi la banda, impedendone di fatto l’accesso ad altri servizi (ad esempio l’invio di posta). Un altro esempio potrebbe essere l’invio massivo di mailing list da parte di un mail server.

In entrambi i casi, se non limito il traffico in uscita, prima o poi la banda internet verrà saturata. Vorrei dunque limitare il traffico in uscita, ad esempio assegnando al traffico HTTP in uscita non più di 3.5Mbps di banda con un burst di 512kbps.

Per far questo, utilizzeremo il comando tc (Traffic Control), presente nelle maggiori distribuzioni Linux.

Conosciamone i concetti chiave:

Token Bucket – Un token bucket può essere considerato come un contenitore di una certa capacità per riservare token (gettoni). Il sistema metterà dei token nel contenitore a una velocità prefissata. Nel caso in cui il contenitore è pieno, i token aggiuntivi usciranno dal contenitore  e  non potranno essere aggiunti altri token. In pratica, con il token bucket possiamo definire la massima velocità di traffico consentita su un’interfaccia in un dato momento nel tempo.

token bucket

rate – la banda che è possibile utilizzare;
ceil – il burst ammissibile in presenza di traffico in eccedenza
prio – la priorità per allocare eventuale banda; le classi con bassa priorità saranno quelle che offriranno banda per prima. Ad esempio, è possibile dare bassa priorità al DNS e priorità più alta all’HTTP per i download;
iptables e tc – È necessario utilizzare insieme iptables e tc per controllare il traffico in uscita.

Vediamo come limitare il traffico in uscita per l’HTTP:

      • Eliminiamo tutte le regole presenti per l’interfaccia di rete eth0:
        tc qdisc del dev eth0 root
      • Abilitiamo la possibilità di accodare i pacchetti (altrimenti verranno scartati):
        tc qdisc add dev eth0 root handle 1:0 htb default 10
      • Definiamo una classe che permette 4096Mbps di banda con un burst di 512Kbps per la porta 80 e priorità 0:
        tc class add dev eth0 parent 1:0 classid 1:10 htb rate 4mbit ceil 512kbps prio 0
      • Fino ad ora la porta 80 non è stata definita da nessuna parte; la definiamo utilizziamo le regole mangle di iptables e successivamente le salviamo:
        iptables -A OUTPUT -t mangle -p tcp --sport 80 -j MARK --set-mark 10
        service iptables save
      • Assegnamo le nostre regole al qdisc:
        tc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:10

Fatto questo, il nostro servizio non occuperà più di 3.5Mbps di banda, con un overspeed (in caso di necessità) di 512Kbps.

Riepiloghiamo i comandi principali:

  • Per vedere le regole esistenti:
    tc -s qdisc ls dev eth0
    tc -s -d class show dev eth0
  • Per cancellare tutte le regole:
    tc qdisc del dev eth0 root
  • Per vedere le regole mangles create:
    iptables -t mangle -n -v -L
  • Per controllare il traffico:
    yum -y install iptraf
    iptraf -i eth0
  • Per vedere in realtime il traffico bassante per il bucket:
    watch tc -s -d class show dev eth0