Una dintre cele mai practice si simple solutii de controlare a traficului in retea este oferita de dummynet(4), implementat in FreeBSD. Dummynet este un traffic shaper, manager de latime de banda (bandwidth) si emulator de intarzieri / pierderi de pachete, creat de Luigi Rizzo (vezi pagina originala aici:
http://info.iet.unipi.it/~luigi/ip_dummynet/). Alte utilizari ale lui dummynet ar fi: emulare pierdere pachete pe link, emulare intarzieri pachete pe link, in vederea testarii comportamentului anumitor servicii in cazul in care creste rata de pierderi si/sau latenta.
Pentru activarea acestuia este nevoie de incarcarea modulului de kernel "dummynet", adaugand linia '
dummynet_load="YES"' in /boot.loader.conf, sau integrarea acestuia in kernel, modificand fisierul de configurare a kernelului astfel incat sa includa:
options IPFIREWALL
options DUMMYNETdupa care se recompileaza kernel-ul. Pentru mai multe detalii, vedeti: man ipfirewall, man dummynet.
Dummynet este controlat prin intermediul utilitarului ipfw. Initial se clasifica pachetele, si se impart in flow-uri, folosind orice model de identificare care se poate folosi in regulile ipfw. In functie de politicile locale, respectivul flow poate include pachete referitoare la: o singura conexiune tcp, catre (sau dinspre) un host, catre (sau dinspre) un subnet intreg, un anume protocol, etc.
Pachetele care sunt incadrate intr-un flow se trimit catre unul dintre urmatoarele obiecte, care implementeaza regularizarea traficului:
- pipe - emulator de legatura cu o anumita latime de banda, cu o anumita intarziere de propagare, lungime coada pachete, rata pierderi pachete
- queue - abstractizare care este folosita pentru implementarea algoritmului WF2Q+ (Worst Case Fair Weighted Fair Queueing), care este o varianta eficienta a politicii WFQ
In practica, un obiect "pipe" este folosit pentru a limita superior latimea de banda alocata unui flow, iar "queue" se foloseste pentru a determina modul in care mai multe flow-uri pot imparti banda disponibila intr-un queue.
Exemplul 1: doua flow-uri, controlate prin pipe-uri diferite
1. creez queue-urile de 1MBit/s si de 512 kbit/s
/sbin/ipfw queue 11 config bw 1Mbit/s
/sbin/ipfw queue 12 config bw 512kbit/s1.1 Verific parametrii pipe-urilor nou create
# /sbin/ipfw pipe 11 show00011: 1.000 Mbit/s 0 ms 50 sl. 0 queues (1 buckets) droptail... 2. Incadrez traficul in 2 flow-uri, in acest caz traficul catre doua host-uri internet distincte
/sbin/ipfw add pipe 11 ip from any to 1.1.1.1/sbin/ipfw add pipe 12 ip from any to 1.1.1.2Atentie: in cazul in care regula de firewall nu va face match niciodata, traficul nu va vi incadrat in flow, si ca atare nu va fi controlat de respectivul pipe/queue.
De exemplu, urmatoarea regula de firewall va face ca traficul trimis de sistemul local catre host-ul cu adresa 1.1.1.1 nu va fi procesat de dummynet, si limitat la 1Mbit/s, urmand circuitul standard al pachetelor IP (de exemplu: legatura LAN Gigabit), in timp ce restul traficului catre 1.1.1.1 si 1.1.1.2 va fi procesat de dummynet:
/sbin/ipfw add pass ip from me to 1.1.1.1
/sbin/ipfw add pipe 11 ip from any to 1.1.1.1/sbin/ipfw add pipe 12 ip from any to 1.1.1.2Exemplul 2: doua queue-uri care impart banda dintr-un pipe (Cozi dinamice / Dymanic queues)
1. configurare pipe
/sbin/ipfw pipe 1 config bw 1Mbit/s queue 32kb2. configurare queue-uri, cu weight-uri diferite
/sbin/ipfw queue 1 config weight 10 pipe 1 mask dst-ip 0xffffffff/sbin/ipfw queue 2 config weight 20 pipe 1 mask dst-ip 0xffffffff3. Clasificare trafic in flow
/sbin/ipfw queue 1 ip from any to 1.1.1.0/24/sbin/ipfw queue 2 ip from any to 1.1.2.0/24In acest exemplu am creat un queue de 1Mbit/s, al carui trafic este partajat cu cuantumuri diferite (weight) de doua queue-uri. aplicand mask dst-ip 0xffffffff am specificat ca toti bitii din adresa ip a destinatiei sunt relevanti pentru diferentierea flow-urilor, adica se vor crea mai multe flow-uri in functie de adresa ip a destinatiei. Traficul in acest caz ar putea fi impartit astfel, daca am 3 host-uri active: host1:1.1.1.1, host2:1.1.1.2, host3:1.1.2.1. Pentru ca traficul spre 1.1.1.1 si 1.1.1.2 e incadrat in queue 1, cu diferentiere pe toti bitii din adresa ip, se vor crea dinamic 2 flow-uri, cu weight 10. Traficul spre 1.1.2.1 va genera un flow cu weight 20. Conform algoritmului WF2Q+, in cazul in care banda ceruta de hosturi atinge sau are tendinta de a depasi maximul specificat in definitia pipe-ului, traficul se va distribui corespunzator weight-urilor flow-urilor active. Adica: flow-ul catre 1.1.1.1 va prelua 25% din traficul din pipe, flow-ul catre 1.1.1.2 va prelua 25% din pipe, iar traficul catre 1.1.2.1 va prelua 50% din pipe. Explicatia e data de faptul ca queue-urile active genereaza o suma a weight-urilor egala cu 40. Din acesti 40, 10 (sau 25% din totalul sumei weight-urilor flow-urilor active) reprezinta weight-ul pentru flow-ul catre 1.1.1.1, iar alti 25%, conform aceleiasi reguli reprezinta traficul flow-ului catre 1.1.1.2, iar 50%.
In cazul in care host-ul 1.1.1.2 nu ar face trafic, situatia se schimba in felul urmator:
suma weight-urilor definite pentru flow-urile active este de 10 + 20 = 30. Din acesti 30 (100%), pentru flow-ul catre 1.1.1.1 se va distribui 33,33% din banda alocata pipe-ului, iar pentru traficul catre 1.1.2.1 se va aloca 66.66%.
In acest fel, este posibil sa se implementeze distribuirea traficului cu minim garantat, si urcare la cel mult cat este alocat in definitia de pipe. Spre exemplu: latimea de banda alocata pe pipe este de 2Mbit/s, intr-o retea cu 50 de utilizatori. Specificand
/sbin/ipfw pipe 1 config bw 2Mbit/s queue 32kb /sbin/ipfw queue 1 config weight 10 queue 1 mask dst-ip 0xffffffff/sbin/ipfw queue 1 ip from any to 1.1.1.0/24este foarte simplu de calculat latimea minima de banda pe care o are disponibila oricand oricare dintre useri: banda_minima = banda_totala / nr_useri = 40kbit/s. In cazul in care exista utilizatori carora trebuie sa le rezerv un disponibil mai mare, le schimb weight-ul flow-urilor traficului lor:
/sbin/ipfw pipe 1 config bw 2Mbit/s queue 32kb /sbin/ipfw queue 1 config weight 10 queue 1 mask dst-ip 0xffffffff/sbin/ipfw queue 2 config weight 30 queue 1 mask dst-ip 0xffffffff
# staff, regula este ca la match-ul regulii de firewall se termina
# cautarile in regulile ipfw, si implicit clasificarea in flow-uri
/sbin/ipfw queue 2 ip from any to 1.1.1.0/28
# others,
mib-ul sysctl net.inet.ip.fw.one_pass=1# daca net.inet.ip.fw.one_pass=0, atunci traficul care iese din queue se
# va reinjecta in firewall , urmand a face alt match, si implicit se va
# clasifica de mai multe ori, cumulativ./sbin/ipfw queue 1 ip from any to 10.1.1.0/24In cazul in care doresc sa rezerv pentru traficul e-mail o anumita latime de banda, am 2 optiuni: ori creez flow-uri intr-un pipe, iar acest trafic nu se va putea face decat la respectiva viteza maxima, ori incadrez traficul intr-un flow cu weight mai mare, pentru a i se aloca o viteza mai mare de transfer
Clasificare trafic cu maxim disponibil per user (Dynamic pipes)
In cazul in care am nevoie sa clasific traficul cu un maxim disponibil oricarui utilizator, pot folosi conceptul de "dymanic pipes", sau pipe-uri dinamice. Acest lucru inseamna ca se creeaza cate un pipe pentru fiecare flow activ la un moment dat. In acest caz nu se poate vorbi despre minim garantat, pentru ca algoritmul WF2Q+ nu opereaza pe pipe-uri, ci pe queue-uri, de la pipe se foloseste doar indicatorul de latime maxima de banda, si nu mai este valabil conceptul "weight".
Exemplu: aloc fiecarui utilizator din subnetul 1.1.1.0/24 un maxim de 1Mbit/s, si fiecarui utilizator din 1.1.2.0/24 un maxim de 2Mbit/s
/sbin/ipfw pipe 1 config 1Mbit/s mask dst-ip ox000000ff/sbin/ipfw pipe 2 config 2Mbit/s mask dst-ip 0x000000ff/sbin/ipfw pipe 1 ip from any to 1.1.1.0/24/sbin/ipfw pipe 2 ip from any to 1.1.2.0/24