Podział pasma pod linuxem w opraciu o HTB (kolejkowanie)
Opracowane przez: 'BiExi'
2005-06-18 22:30

W dzisiejszych czasach gdy wiekszość użytkowników używa p2p, a my jako dostawcy internetu posiadamy łącze o niskiej przepustowości za które bulimy straszne pieniądze chielibyśmy w jakiś sposób regulować ruch w naszej sieci. Sposobem na to jest podział pasma. Mamy kilka różnych metod kolejkowania. Ja się zajmę HTB, ponieważ jest ona jedną z bardziej wydajnych...

Co nam będzie potrzebne
- troche czasu
- kernel - najlepiej najnowszy
- iproute

a więc zasysamy kernela i kompilujemy go z następującymi opcjami:

 Networking options  --->  
   <*> Packet socket 
   [*]   Packet socket: mmapped IO
   <*> Netlink device emulation
   [*] Network packet filtering (replaces ipchains)
   [*]   Network packet filtering debugging
   [*] Socket Filtering 
   <*> Unix domain sockets 
   [*] TCP/IP networking   
  IP: Netfilter Configuration  ---> 
   <*> Connection tracking (required for masq/NAT)  
   <*> IP tables support (required for filtering/masq/NAT) 
      netfilter MARK match support 
  QoS and/or fair queueing  --->  
      [*] QoS and/or fair queueing 
      <*>   CBQ packet scheduler
      <*>   HTB packet scheduler
      <*>   CSZ packet scheduler
      <*>   H-FSC packet scheduler
      <*>   The simplest PRIO pseudoscheduler
      <*>   RED queue
      <*>   SFQ queue
      <*>   TEQL queue 
      <*>   TBF queue
      <*>   GRED queue 
      <*>   Network emulator 
      <*>   Diffserv field marker 
      <*>   Ingress Qdisc
      [*]   QoS support
      [*]     Rate estimator
      [*]   Packet classifier API
      <*>     TC index classifier 
      <*>     Routing table based classifier 
      <*>     Firewall based classifier 
      <*>     U32 classifier    
      <*>     Special RSVP classifier
      <*>     Special RSVP classifier for IPv6 
      [*]     Traffic policing (needed for in/egress)   

teraz troche info na temat naszej przykładowej sieci
eth0 - interfejs wyjścia na świat
eth1 - interfejs wyjścia na lan
192.168.1.1 - ip na eth1
192.168.1.2 - user nr 1
192.168.1.3 - user nr 2
192.168.1.4 - user nr 3
posiadamy łącze powiedzmy 0,5 megabit'a

Założenia:
user nr 1
15 kilo - gwarantowany dawnload
40 kilo - maksymalny dawnload
15 kilo - upload

user nr 2
10 kilo - gwarantowany dawnload
30 kilo - maksymalny dawnload
10 kilo - upload

user nr 3 10 kilo - gwarantowany dawnload
30 kilo - maksymalny dawnload
10 kilo - upload

teraz nasze przykładowe kolejki:

Kolejka główna - download

kasujemy główną kolejkę na interfejs eth1

tc qdisc del dev eth1 root handle 1:0 htb

tworzymy nowa kolejke glowna kolejke na interfejs eth1

tc qdisc add dev eth1 root handle 1:0 htb

Teraz przydział pasma na kolejkę. Ze względu że jest to karta sieciowa to ustawiamy jej przepustowość 10mbit. Dla niej rodzicem jest kolejka 1:0 którą wcześniej stworzyliśmy. O tym, z której kolejki dziedziczymy dowiadujemy się z parametru parent. Nasza kolejka potomna jest oznaczona przez classid jako 1:1
Parametr rate - określa minimalny gwarantowany transfer
Parametr ceil - mówi nam ile maksymalnie pasma można wypożyczyć
Parametr quantum - wylicza się go z rate, mianowicie rate*1024/8/1600 - pozwala on uniknąć niektórych błędów pojawiających się w logach.

tc class add dev eth1 parent 1:0 classid 1:1 htb rate 10mbit ceil 11mbit quantum 768

Kolejka której rodzicem jest 1:1, gdzie ustawiamy rate i cail na ciut mniej niż 0,5 megabit'a

tc class add dev eth1 parent 1:1 classid 1:2 htb rate 480kbit ceil 480kbit quantum 768

Teraz tworzymy kolejną potomną kolejkę dla której rodzicem jest wyżej napisana kolejka gdzie podajemy ciut mniejsze rate niż w kolejce która jest rodzicem. Rodzic 1:1 ma 10 megabitów, a potomstwo ma 9000 kilobitów, i jest oznaczone jako 1:3

tc class add dev eth1 parent 1:1 classid 1:3 htb rate 9000kbit ceil 9000kbit quantum 768

Teraz tworzymy sobie filtr dla naszej kolejki, w którym wpisujemy ip interfejsu eth1, tak aby nic nie blokowalo mu transferu lokalnego

tc filter add dev eth1 protocol ip preference 1 parent 1:0 u32 match ip src 192.168.1.1 flowid 1:3

Finalizacja ustawień dla kolejki dla 192.168.1.1 czyli ustawienie metody kolejkowania - w moim przypadku jest to fifo (first in firt out). (Pierwszy wszedł pierwszy wyjdzie) :]

tc qdisc add dev eth1 parent 1:3 handle 299:0 sfq perturb 10

ok, kolejkę główną mamy zdfiniowaną, teraz pora na userow :] A wiec dla naszej kolejki dla userów, rodzicem jest 1:2 a nasza kolejka jest oznaczona jako 1:5 i jest ustawione rate i cail jako przedział transferu dla danego user'a, Dodatkowo pojawia się tu parametr burst oznaczający ile danych może być ściągniętych bez ograniczenia pasma. Dobrą sprawą jest używać tego parametru by strony www się szybko ładowały

tc class a dev eth1 parent 1:2 classid 1:5 htb rate 100kbit ceil 320kbit quantum 1 burst 10k

i robimy filtr, w którym podajemy IP którego ma dotyczyć kolejka, czyli w naszym przypadku 192.168.1.2 Łącznikiem jest tu wartość classid 1:5

tc filter add dev eth1 protocol ip preference 2 parent 1:0 u32 match ip dst 192.168.1.2 flowid 1:5

określenie metody kolejkowania, również na fifo występuje tu parametr handle. No musi być inny dla każdej potomnej kolejki

tc qdisc add dev eth1 parent 1:5 handle 50:0 sfq perturb 10

teraz jeszcze wizualny przykład z kolejkami dla pozostalych 2 adresow IP user nr 2

tc class a dev eth1 parent 1:2 classid 1:6 htb rate 60kbit ceil 220kbit quantum 1 burst 10k
tc filter add dev eth1 protocol ip preference 2 parent 1:0 u32 match ip dst 192.168.1.3 flowid 1:6
tc qdisc add dev eth1 parent 1:6 handle 51:0 sfq perturb 10

user nr 3

tc class a dev eth1 parent 1:2 classid 1:7 htb rate 60kbit ceil 220kbit quantum 1 burst 10k
tc filter add dev eth1 protocol ip preference 2 parent 1:0 u32 match ip dst 192.168.1.4 flowid 1:7
tc qdisc add dev eth1 parent 1:7 handle 53:0 sfq perturb 10

Teraz zajmiemy się uploadem. Zasada jest tu troche inna, ze względu ze server za bardzo nie może okreslić
do kogo ma trafić pakiet, to musimy sobie te pakiety oznaczać. Najprostsza metoda to markowanie pakietów za pomocą iptables

kasujemy główną kolejkę

tc qdisc del dev eth0 root handle 1:0 htb

tworzymy ją

tc qdisc add dev eth0 root handle 1:0 htb

tu jest ta sama zasada co wyżej

tc class add dev eth0 parent 1:0 classid 1:1 htb rate 500kbit ceil 500kbit quantum 43
tc class add dev eth0 parent 1:1 classid 1:2 htb rate 480kbit ceil 480kbit quantum 41
tc qdisc add dev eth0 parent 1:2 handle 2:0 sfq perturb 10";
tc filter add dev eth0 protocol ip preference 1 parent 1:0 handle 2000 fw flowid 1:2

Tworzymy sobie nowy łańcuch o nazwie UPIERDALACZ_ETH0

iptables -t mangle -N UPIERDALACZ_ETH0

kasujemy łańcuch przy przeładowywaniu kolejki się przydaje

iptables -t mangle -D POSTROUTING -o eth0 -j UPIERDALACZ_ETH0

zakładamy łańcuch na eth0

iptables -t mangle -I POSTROUTING -o eth0 -j UPIERDALACZ_ETH0

teraz upload dla userów
analogicznie do tego co było wcześniej

tc class add dev eth0 parent 1:2 classid 1:5 htb rate 110kbit ceil 110kbit quantum 3 burst 5k
tc qdisc add dev eth0 parent 1:5 handle 50:0 sfq perturb 10

Tutaj należy zwrócić uwagę na wartość parametru handle - jest to właśnie uchwyt który łączy markowane pakiety z naszą kolejką

tc filter add dev eth0 protocol ip preference 2 parent 1:0 handle 60 fw flowid 1:5

usuwamy marker iptables dla tego IP

iptables -t mangle -D UPIERDALACZ_ETH0 -p tcp -s 192.168.1.2 -j MARK --set-mark 60 >>/dev/null

markujemy pakiety pochodzące z ip 192.168.1.2

iptables -t mangle -A UPIERDALACZ_ETH0 -p tcp -s 192.168.1.2 -j MARK --set-mark 60

przykład dla pozostałych 2 IP user nr 2

tc class add dev eth0 parent 1:2 classid 1:6 htb rate 70kbit ceil 70kbit quantum 3 burst 5k
tc qdisc add dev eth0 parent 1:6 handle 50:0 sfq perturb 10
tc filter add dev eth0 protocol ip preference 2 parent 1:0 handle 61 fw flowid 1:6
iptables -t mangle -D UPIERDALACZ_ETH0 -p tcp -s 192.168.1.3 -j MARK --set-mark 61 >>/dev/null
iptables -t mangle -A UPIERDALACZ_ETH0 -p tcp -s 192.168.1.3 -j MARK --set-mark 61

user nr 3

tc class add dev eth0 parent 1:2 classid 1:7 htb rate 70kbit ceil 70kbit quantum 3 burst 5k
tc qdisc add dev eth0 parent 1:7 handle 50:0 sfq perturb 10
tc filter add dev eth0 protocol ip preference 2 parent 1:0 handle 62 fw flowid 1:7
iptables -t mangle -D UPIERDALACZ_ETH0 -p tcp -s 192.168.1.4 -j MARK --set-mark 62 >>/dev/null
iptables -t mangle -A UPIERDALACZ_ETH0 -p tcp -s 192.168.1.4 -j MARK --set-mark 62

No, i użytkowników mamy już zakolejkowanych

i jeszcze zamarkujemy na koniec pakiety nieznanego pochodzenia

iptables -t mangle -A UPIERDALACZ_ETH0 -m mark --mark 0 -j MARK --set-mark 2000

OK teraz cos dla leniwych :] mianowicie, mały skrypt upierdalacz - można go sobie ściągnać i używać nie zminiając praw autorskich

upierdalacz.tar.gz

rozakowujemy to w /etc powstanie nam nowy katalog, w którym znajdują sie 2 pliki kolejka i plik upierdalacz.List który wygląda tak:

# Configuration uperdalacz.list for eth1 # :::::::::::::::::::::::::::::::::::::::::::::::::
# | IP | GW | MAX | Opis
# :::::::::::::::::::::::::::::::::::::::::::::::::
192.168.1.2 ; 60 ; 300 ; 100 ; user1
192.168.1.3 ; 60 ; 230 ; 70 ; user2
192.168.1.4 ; 60 ; 230 ; 70 ; user3
#end file

gdzie 1 kolumna to ip użytkownika
2 kolumna minimalny gwarantownay transfer
3 kolumna to maksymalny transfer
4 kolumna transferna upload
5 kolumna opis
i plik z właściwym skryptem "kolejka" :]