Linux zarządzanie pasmem transmisji danych

Przygotowanie systemu do podziału pasma

Opisany system praktycznie może już pracować jako ruter. Będzie to jednak sytuacja, w której każdy z klientów zdefiniowanych w NAT będzie miał możliwość wykorzystania całego pasma dostępnego dla serwera. Tego typu uproszczenie możemy zastosować w sieciach, w których jest bardzo mało klientów (mniej niż 10). W praktyce jednak nawet przy 5 klientach, gdy jeden z nich pobiera filmy, to rozwiązanie okazuje się niewystarczające.

Graficznie przedstawia je rysunek w punkcie 2. Takie rozwiązanie wykorzystuje łącze nieoptymalnie z punktu widzenia ISP. Dzieląc w ten sposób łącze, dochodzimy do sytuacji opisanej na wstępie, gdy 512 kb/s podzielimy tylko na 8 osób.

Dlatego nasze działania będą się skupiały na podzieleniu pasma w taki sposób, by nie gwarantować użytkownikom żadnej przepustowości (lub gwarantować tylko znikomą), a przydzielać im maksymalne prawo do obciążenia łącza. W uproszczeniu można powiedzieć, że użytkownicy pożyczają sobie łącze w trakcie korzystania z niego. Istotną sprawą jest monitoring łącza i obserwacja, czy nie dochodzi do przeciążeń. Możemy bowiem sprzedawać więcej niż mamy, jednak pod warunkiem, że nam tego nie zabraknie. Rozwiązanie to jest niezauważalne dla klientów, ponieważ osiągają oni swoje pasmo, a nam pozwala ono zaoferować niższą cenę, bo możemy podłączyć więcej klientów do jednego łącza.

Skrypt bazowy.sh

#!/bin/bash

IP_zew=10.10.1.2

IP_wew=192.168.0.1

#czyszczenie ustawień iptables

iptables -F

iptables -F -t nat

iptables -X -t nat

#dla lstata - statystyki transmisji danych

iptables -F lstat

iptables -X lstat

iptables -N lstat

##tutaj każdego klienta na WE i WY

#Klient 1

iptables -A lstat -m state -state ESTABLISHED,RELATED -d 192.168.0.10 -j ACCEPT

iptables -A lstat -m state -state ESTABLISHED,RELATED -s 192.168.0.10 -j ACCEPT

#Klient 2

iptables -A lstat -m state -state ESTABLISHED,RELATED -d 192.168.0.11 -j ACCEPT

iptables -A lstat -m state -state ESTABLISHED,RELATED -s 192.168.0.11 -j ACCEPT

#itd.

#tutaj przekazywanie pakietów przechodzących przez ruter do łańcucha lstat

iptables -I FORWARD -j lstat

#blokowanie tych, co nie płacą

#zły klient3 - wymaga to odpowiednich ustawień

iptables -I PREROUTING -t nat -s 192.168.0.12 -d ! 192.168.0.1 -p tcp -dport 80 -j DNAT -to-destination 192.168.0.1:200

#ustawienia NAT

#Klient 1

iptables -t nat -A POSTROUTING -s 192.168.0.10 -j SNAT -to $IP_zew

#Klient 2

iptables -t nat -A POSTROUTING -s 192.168.0.11 -j SNAT -to $IP_zew

Sprawa wygląda już wręcz idealnie. Podział pasma realizowany jest na podstawie tzw. klas. Definiujemy klasę, do której jest przypisana przepustowość maksymalna, a dopiero w dalszej kolejności przypisujemy do odpowiedniej klasy adresy IP. Opisany algorytm wykorzystuje kolejkowanie oparte na HTB (Hierachical Token Bucket). Szczegółowy opis algorytmu nie jest jednak celem tego artykułu. Zainteresowanych odsyłamy na stronę autora HTB -http://luxik.cdi.cz/~devik/qos/htb/ .

Bardzo ważną sprawą jest poznanie możliwości Linuxa i innych systemów w tym zakresie. Kolejkowanie i podział może być dokonany tylko i wyłącznie przy wyjściu z interfejsu sieciowego. Ruch wejściowy (pobieranie danych) powinniśmy więc ograniczać na karcie sieciowej wewnętrznej (u nas eth1 na rysunku w punkcie 3.), a ruch wyjściowy (wysyłanie danych) na karcie sieciowej zewnętrznej (u nas eth0).

Należy jednak zauważyć, że w przypadku zastosowania NAT nie ma możliwości określenia na interfejsie zewnętrznym adresu źródłowego. Nie da się więc filtrować konkretnego klienta, ponieważ karta zewnętrzna nie zna nadawcy - jego adres IP został już zamaskowany (rysunek - punkt 4.).

Rozwiązaniem jest zastosowanie wirtualnego interfejsu IMQ (Intermediate Queueing Device). Wykorzystanie tego mechanizmu pozwala nam ograniczać ruch wychodzący w zależności od nadawcy NAT, zachowując zasadę, że możliwe jest tylko ograniczanie na wyjściu z interfejsu. Tym interfejsem, na którym wprowadzamy ograniczenia jest właśnie IMQ (rysunek - punkt 5.).

Skrypt ściąganie.sh

#!/bin/bash

#

#

# Aby dodać użytkownika, trzeba:

# 1. Zdefiniować jego szybkość.

# 2. Określić filtr przydziału do tej klasy.

# 3. Ustawić mu SFQ (żeby sam się nie zapchał - np. pobiera film i nie działa WWW).

#

#

min=5kbit

max=64kbit

#

# czyszczenie

tc qdisc del root dev eth1

#przydzielanie domyślnego kanału głównego i określenie domyślnej klasy

tc qdisc add dev eth1 root handle 1:0 htb

#definicja klasy głównej - tyle mamy pasma

tc class add dev eth1 parent 1:0 classid 1:1 htb rate 512kbit ceil 512kbit

#definiowanie klas

tc class add dev eth1 parent 1:1 classid 1:2 htb rate $min ceil $max

tc class add dev eth1 parent 1:1 classid 1:3 htb rate $min ceil $max

# filtry przydziału do klas

#Klient 1

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

#Klient 2

tc filter add dev eth1 protocol ip parent 1:0 u32 match ip dst 192.168.0.11 flowid 1:3

# sfq - kolejka w ramach klasy

tc qdisc add dev eth1 parent 1:2 handle 2:0 sfq perturb 1

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


TOP 200