Spis treści

Wstęp i wymagania

Celem działania NiceShapera jest umożliwienie optymalnego wykorzystania łącza internetowego oraz uproszczenie konfiguracji, złożonego zagadnienia jakim jest kształtowanie ruchu sieciowego w Linuksie. Projektując rozwiązania staram się by były one elastyczne, intuicyjne i przejrzyste, by upraszczały to co niepotrzebnie skomplikowane, ale też udostępniały możliwość konfigurowania tego, nad czym warto mieć kontrolę.

Możliwe jest wstępne stworzenie dobrze działającego podziału łącza, bez zapoznania się z tą dokumentacją, używając dołączonych przykładowych plików konfiguracyjnych, pod warunkiem posiadania w miarę solidnych podstaw z zakresu działania sieci. Należy mieć jednak świadomość, że po przyjrzeniu się dołączonym przykładowym plikom konfiguracyjnym i pierwszym uruchomieniu NiceShapera, wypada zapoznać się z niniejszą dokumentacją, w przeciwnym wypadku może nie udać się stworzyć optymalnie działającego podziału łącza. NiceShaper bardzo się stara, ale nie jest w stanie odgadnąć wszystkich Twoich intencji, dlatego wiedza z zakresu sieci oraz systemu Linux jest ważna. Nie należy się jednak zrażać czytając dokumentację, gdyż wykracza ona poza minimum potrzebne do uruchomienia podstawowego podziału łącza. W końcu NiceShaper ma ułatwiać to co w HTB trudne, ale jednocześnie dostarczać dodatkowych możliwości.

W minimalnej konfiguracji niezbędny jest router z systemem Linux z programem iptables i wkompilowanymi w kernel: kolejką HTB, algorytmem kolejkowania SFQ oraz filtrem kernela U32.

W dalszej części dokumentacji klasy HTB nazywane będą właśnie kolejkami HTB, tak by nie były one mylone z klasami NiceShapera. SFQ i inne bezklasowe dyscypliny kolejkowania to algorytmy kolejkowania. Filtry U32 i FW to filtry kernela, by nie były mylone z filtrami NiceShapera.

W najpopularniejszych dystrybucjach Linuksa HTB, SFQ oraz filtry U32 i FW są domyślnie wkompilowane w kernel lub dostarczane w formie modułów. Program iptables, pomijając obsługę IMQ, podobnie.

Na potrzeby dokumentacji, przyjmujemy, że posiadamy router z dwoma interfejsami. Łącze internetowe podłączone jest do interfejsu eth0, sieć lokalna do eth1. Adres publiczny routera to 198.51.100.100, prywatny 192.168.0.1 a adresacja sieci lokalnej to 192.168.0.0/24.

Pomijając ograniczony ingress qdisc, którego NiceShaper nie używa, kształtowanie ruchu odbywa się na interfejsie, którym, kontrolowany ruch opuszcza router. Zatem, dla powyższych założeń, kształtowanie downloadu klientów odbywać się będzie na interfejsie eth1, gdyż pakiet z internetu wchodzi do routera interfejsem eth0 i po przeforwardowaniu, skierowany do klienta, opuszcza go właśnie interfejsem eth1. Odwrotna sytuacja zachodzi dla uploadu. Pakiet transmitowany przez klienta, wchodzi do routera przez interfejs eth1, by po przeforwardowaniu opuścić go interfejsem eth0. Zatem kształtowanie uploadu powinno się odbywać na interfejsie eth0. Należy bezwzględnie pamiętać, że ten akapit jest prawidłowy wyłącznie dla powyższych założeń i może być wymagane, dopasowanie konfiguracji, przed uruchomieniem w odmiennym środowisku!

Dobór interfejsów będzie kluczowy do zdefiniowania klas NiceShapera oraz dla części z dyrektyw konfiguracyjnych operujących na interfejsach. Przykładowo jeśli sieć LAN znajduje się za NATem i chcemy obsłużyć upload metodą markowania pakietów, mechanizm ten należało by włączyć na interfejsie eth0 (dyrektywa mark-on-ifaces eth0)

Nawiasem mówiąc, wspomniana kontrola pasma wychodzącego z sieci ukrytej za NATem, poza markowaniem pakietów, możliwa jest do zrealizowana za pomocą interfejsów IMQ. Ponadto interfejsy IMQ mogą zostać wykorzystane, do kontroli pasma przychodzącego routera. Obydwa mechanizmy zostały opisane w dalszej części dokumentacji.

Przypominam, wskazane interfejsy są poprawne dla poczynionych założeń a nie dla każdego routera!

Na koniec akapit o oznaczaniu interfejsów sieciowych. Iptables i Iproute nie rozróżniają aliasów interfejsów, które nawiasem mówiąc, są przestarzałym rozwiązaniem z czasów powszechnego stosowania polecenia ifconfig. Polecenie ifconfig zostało z powodzeniem zastąpione przez polecenie ip. Stąd w przypadku takich interfejsów z aliasami, w konfiguracji NiceShapera pomijamy część aliasową czyli dwukropek i liczbę za nim. Natomiast VLANy zapisywane w formie ethX.vid, są w pełni obsługiwane.

Uzupełniając temat obsługi VLANów w Linuksie. Jeśli podnoszony jest sub interfejs tagowany i uruchomione na nim zostaje kształtowanie ruchu, warto całkowicie zrezygnować z przypisywania adresu i podnoszenia interfejsu nietagowanego. W przeciwnym wypadku może się okazać, że kernel podda tagowane pakiety dwukrotnemu kolejkowaniu. Raz na tagowanym sub interfejsie oraz kolejny raz na fizycznym.

NiceShaper bardzo dobrze skaluje się, na routerach obsługujących do około pięciuset hostów - choć pojawiają się doniesienia o bezproblemowej pracy w większych sieciach. W takich sieciach niezbędne okazują się być tablice mieszające, których użycie w NiceShaperze, ze względu na zbyt małą elastyczność, nie jest aktualnie planowane.

Instalacja

Opis dotyczy instalacji z pakietu źródłowego. Do jej przeprowadzenia niezbędny jest kompilator c++ z pakietu gcc, biblioteki standardowe c i c++ oraz program make. Rozpakowany pakiet kompiluje się z pominięciem ./configure, gdyż NiceShaper jest nieprzenośny - działa wyłącznie pod Linuksem.

Procedura kompilacji i instalacji:

$ bunzip2 niceshaper-%{wersja}.tar.bz2
$ tar xf niceshaper-%{wersja}.tar
$ cd niceshaper-%{wersja}
$ make
$ su
# make install
Polecenie make install skopiuje skompilowany program do katalogu /usr/local/bin. Ścieżka może zostać zmieniona za pomocą zmiennej środowiskowej BINDIR. Automatycznie utworzone zostaną wymagane katalogi: /etc/niceshaper, /var/lib/niceshaper oraz /usr/share/doc/niceshaper. Przykładowe pliki konfiguracyjne zostaną skopiowane do katalogu /etc/niceshaper. Jeśli pliki konfiguracyjne już istnieją nie zostaną one nadpisane lecz pliki w nowych wersjach zostaną skopiowane z postfixem "-dist". Dokumentacja oraz pozostała zawartość pakietu zostanie skopiowana do katalogu /usr/share/doc/niceshaper.

Konfiguracja

Składnia plików konfiguracyjnych

Wymagane podstawowe pliki konfiguracji to /etc/niceshaper/config.conf oraz /etc/niceshaper/class.conf.
include file ścieżka - dyrektywa include użyta w tych plikach pozwala włączać kolejne. Dyrektywa include obsługuje ścieżki absolutne (z rozpoczynającym znakiem slash) oraz relatywne do katalogu konfiguracyjnego (domyślnie /etc/niceshaper).
Konfiguracja składa się z kilku typów dyrektyw, różniących się składnią:
Typ 1) parametr wartość - czyli parametr z przypisaną mu wartością, np.:
rate 128kB/s
Typ 2) parametr wartość [wartość] - czyli parametr z przypisanymi mu rozdzielonymi białymi znakami (spacja, tabulator) wartościami, np.:
mark-on-ifaces eth0 eth1
Typ 3) dyrektywa parametr wartość [parametr wartość] - czyli dyrektywa z listą parametrów i wartości, wymienionych parami, np.:
status file /var/www/niceshaper/status.txt unit kB/s file-mode 644
W przypadku wszystkich trzech wymienionych powyżej typów, kolejność dyrektyw i parametrów nie jest istotna.

W przypadku typów 2 i 3, czyli list, parser konfiguracji automatycznie rozbija podane wartości lub pary parametrów z wartościami. Więc w ramach własnych preferencji, powyższe przykłady, można także zapisać następująco:

Typ 4) Dyrektywa match to składniowo dyrektywa typu 3, jednak nie można jej rozbijać na osobne linie. Dozwolona jest wyłącznie dowolność w kolejności par parametrów. Rozbicie parametrów zburzyło by sens i spójność filtra.
Przykładowy, poniżej, filtr klasyfikujący pakiety z adresem źródłowym 10.10.10.5 oraz jednocześnie docelowym z zakresu sieci 192.168.0.0/29:
match srcip 10.10.10.5 dstip 192.168.0.0/29
Po rozbiciu tworzy 2 niezależne filtry:
Same w sobie są one poprawne, ale nie są tożsame z filtrem wyjściowym.
Typ 5) Zapis dyrektywy class nie podlega żadnej elastyczności. np.:
class dl eth1 pc55
Poza różnicami składniowymi dyrektywy dzielą się ze względu na zasięg funkcjonowania na: dyrektywy sekcji global, dyrektywy sekcji funkcjonalnych oraz dyrektywy klas. Jeśli chodzi o dyrektywy klas, wszystkie poza nagłówkiem klasy oraz filtrem mogą zostać umieszczone w konfiguracjach sekcji funkcjonalnych. Tym samym dostarczając wartości domyślnych dla wszystkich klas wchodzących w skład takiej sekcji.W dalszej części dokumentacji te trzy grupy są wyraźnie rozdzielone.

Podstawowe jednostki przepustowości to b/s - bit na sekundę, oraz B/s - bajt na sekundę. Poprawne przedrostki to k-kilo oraz M-mega. Dopisek '/s' nie jest obowiązkowy a rozróżnienie między przepustowością a ilością przesłanych danych odbywa się na podstawie kontekstu. Jednostką domyślną przepustowości jest b/s (bit na sekundę).

NiceShaper udostępnia kilka znaków specjalnych. Znak "#" jest komentarzem i odnosi się do reszty linii występującej za nim. Znaki "<# komentarz #>" również tworzą komentarz, z tą różnicą że stosuje się je w parze a obejmują dowolny wycinek linii konfiguracyjnej. Oczywiście zakomentowana część konfiguracji nie jest brana pod uwagę. Kolejny znak specjalny, znak średnika, zastępuje przejście do nowej linii konfiguracji, pozwala zminimalizować długość pliku konfiguracyjnego klas, czasem pozytywnie a czasem negatywnie wpływa na czytelność.

Wszystkie zmiany w konfiguracji wymagają zrestartowania programu.

Wszystkie konfiguracje dostarczone z pakietem są tylko przykładami i nie są optymalne dla każdej sieci - choć są dobrym materiałem wyjściowym do wdrożenia programu.

Główny plik konfiguracyjny, na przykładzie

Domyślnie głównym plikiem konfiguracyjnym jest plik /etc/niceshaper/config.conf. Jest on podzielony na sekcje. Do prawidłowego działania niezbędna jest jedna i tylko jednak sekcja o nazwie global, zawierająca główną konfiguracje programu oraz minimum jedna a w praktyce dwie lub nawet więcej sekcji funkcjonalnych. Sekcja funkcjonalna jest kontenerem grupującym klasy NiceShapera. Z reguły odzwierciedla jeden z kierunków przepływu ruchu przez łącze internetowe, tak więc każde łącze obsługiwane jest przez minimum dwie sekcje. Każda sekcja dysponuje własną konfiguracją, własną listą klas oraz parametrami domyślnymi dla tych klas. W skład sekcji wchodzić mogą klasy pracujące na różnych interfejsach, a na każdym interfejsie pracować mogą, klasy wchodzące w skład różnych sekcji.

Przykładowa zawartość głównego pliku konfiguracyjnego:

Opcje sekcji global:

Opcje sekcji funkcjonalnych:

W konfiguracji sekcji umieścić można każdą z dyrektyw i parametrów klas (opisanych w dalszej części dokumentacji), stają się one wtedy domyślnymi dla wszystkich klas tej sekcji.

Hosty i klasy NiceShapera

Plik /etc/niceshaper/class.conf zawiera definicję hostów i/lub klas. Klasy można uznać za odpowiednik lub bardziej rozszerzenie kolejek w HTB. Składniowo klasa zbudowana jest z nagłówka, minimum jednego filtra oraz opcji konfiguracyjnych. Odpowiadająca klasie kolejka w HTB jest tworzona kiedy klasa wykazuje aktywność a wyładowywana po ustalonym czasie bezczynności. Dzięki temu w tym samym czasie w HTB występują kolejki wyłącznie aktywnych klas a nie wszystkich zdefiniowanych, co daje optymalne wartości parametru rate kolejek HTB. Każdy pakiet opuszczający interfejs, zostaje sklasyfikowany za pomocą filtrów, do pierwszej pasującej klasy (faktycznie do kolejki HTB).

Należy zadbać, by zadeklarowane klasy NiceShapera obsługiwały, cały wykorzystujący łącze ruch. W przeciwnym razie pojawią się niemożliwe do kontrolowania przecieki. Np. w przypadku gdy nie wszystkie hosty w sieci lokalnej zostaną przypisane do klas, te niekontrolowane będą odbierały pasmo pozostałym.

Hosty:

Klasy są zaawansowanym oraz bardzo elastycznym narzędziem. Jednak to dyrektywa host jest najczęściej wystarczającym i jednocześnie bardzo przyjaznym oraz przejrzystym sposobem, na stworzenie sprawiedliwego podziału łącza dla wszystkich lub większości standardowych użytkowników sieci. Jest to jeden z tych elementów, dzięki którym konfiguracja podziału łącza w NiceShaperze jest tak wygodna. Hosty umożliwiają wygodną konfigurację podziału łącza, nawet bez zapoznawania się z klasami!

Do zdefiniowania hosta potrzebne są: lista sekcji w których ma on być umieszczony wraz z interfejsami na których ma następować kształtowanie ruchu, adres ip oraz nadana nazwa. Host może należeć do dowolnych z uruchomionych sekcji, ale musi należeć przynajmniej do jednej. NiceShaper sam zajmie się przetłumaczeniem dyrektywy host na odpowiednie klasy i filtry.

Można przyjąć, że dyrektywa host to funkcjonalnie pewnego rodzaju makro NiceShapera.

Definicja hosta mieści się zawsze w jednej linii. Składniowo wygląda następująco:

host sekcja interfejs [sekcja interfejs] ip nazwa
Przykładowo:
Powyższe przykładowe definicje hostów zostaną, przez parser konfiguracji, rozłożone na następujące klasy:
NiceShaper wstawia do filtrów test dstip lub srcip, zależnie od trybu sekcji.

Host wskazywany jest wyłącznie za pomocą adresu IP. Tam gdzie potrzebne są dodatkowe możliwości filtrowania lub nadpisywania parametrów domyślnych, tam wkraczają klasy.

UWAGA: Powyższy przykład hosta pc11, przypisanego tylko do jednej sekcji, ma za zadanie wyłącznie naświetlenie składni dyrektywy. Nigdy nie należy pozostawiać żadnego z hostów w sieci bez kontroli, szczególnie w zakresie uploadu.

Budowa klasy:

W aktualnej wersji NiceShaper udostępnia 4 typy klas. Są to klasa standardowa oraz klasy o specjalnym przeznaczeniu: virtual, wrapper oraz do-not-shape. Przy czym ostatnie dwa typy opisane zostały w rozdziale "Jak traktować ruch z i do routera".
Definicję klasy rozpoczyna nagłówek klasy a kończy nagłówek kolejnej.

Nagłówek klas typów standardowego i virtual wygląda następująco:

class|class-virtual sekcja interfejs nazwa
Gdzie:

sekcja - sekcja w skład której wchodzi klasa.
interfejs - interfejs na którym realizowane jest kolejkowanie klasy za pomocą HTB.
nazwa - nazwa klasy, wyświetlana m.in. przez status.

Obowiązkowym parametrem ciała klasy jest filtr:

match test <test> [test <test>]
Filtry wskazują ruch którym dana klasa będzie zarządzać. Oczywiście mowa tu o ruchu wychodzącym czyli opuszczającym router, interfejsem na którym klasa działa. Jeśli zachodzi taka potrzeba, co opisane zostało już w rozdziale "współpraca z iptables", odpowiednie wpisy tworzone są przez NiceShapera w iptables w łańcuchu sekcji, jak i tworzony jest filtr kernela, za zadanie mający kierowanie ruchu do odpowiedniej kolejki HTB kształtującej pasmo. Naturalnie testy można ze sobą łączyć, by uzyskać bardziej szczegółowe filtry, zaś w skład klasy wchodzić może dowolna liczba filtrów.

Przykładowa najprostsza klasa ma postać:

Lub przykłady w zwiniętej postaci (w dalszej części dokumentacji używany jest pierwszy sposób zapisu):

Parametry klas:

Jak już wspomniano, wszystkie powyższe dyrektywy i parametry mogą zostać użyte w konfiguracji sekcji, by parametrów nie powtarzać dla każdej klasy z osobna. Następnie jeśli zaistnieje potrzeba zróżnicowania ustawień poszczególnych klas, nadpisać wybrane z nich.

Testy podstawowe:

srcip oraz dstip mogą wskazywać adres ip lub podsieć adresów o zasięgu zdefiniowanym w standardowy sposób przez maskę, zapisaną w formacie bitowym lub kropkowo-dziesiętnym. Maska nie musi być ciągła (np. 255.255.128.255) jednak należy pamiętać że takiej sytuacji nie obsługuje filtr kernela U32 i dla masek nieciągłych trzeba posłużyć się markowaniem pakietów.

Przykładowe filtry:

Testy wymagające włączonego markowania na interfejsie:

Filtr pakietów iptables został zaopatrzony w olbrzymią liczbę filtrów, które nie są niestety możliwe do zrealizowania przy użyciu filtra kernela U32. Dlatego też poniższe filtry wymagają włączenia markowania pakietów za pomocą dyrektywy mark-on-ifaces. Każdy pakiet dopasowany i oznaczony przez automatycznie wprowadzone reguły iptables, może już być bez problemu skierowany do odpowiedniej kolejki HTB a to dzięki filtrowi kernela FW który w efekcie użycia dyrektywy mark-on-ifaces zostaje użyty w miejsce filtra U32.

Uwaga. Niektóre z poniższych filtrów mogą nie działać na okrojonej kompilacji kernela i/lub iptables.

Makra pliku klas

Makra pliku klas mają za zadanie usprawnić tworzenie wielu klas, jeśli te są podobne do siebie. Działając w pętli, powielają dowolny wycinek pliku klas. Makro składa się z nagłówka, treści oraz zamknięcia. Nagłówek to nawias klamrowy zawierający typ oraz parametry pętli. Treść jest poprawną zawartością pliku klas. Treść zaopatrzona jest w znaki $ (dolar), oraz % (procent), w każdej iteracji pętli zastępowane odpowiednimi danymi. Zamknięcie to nawias klamrowy z ukośnikiem wewnątrz, czyli trzy znaki: {/}.

W aktualnej wersji NiceShapera zaimplementowane są 3 typy makr - sequence, foreach-elem, foreach-pair.

Makro sequence:

{sequence od do} treść {/} - Makro sequence generuje wartości we wskazanym zakresie, rosnąco. Wartości "od" oraz "do" muszą być wartościami liczbowymi, dodatnimi, z przedziału od 0 do 65535. Kolejne wartości wstawiane są w miejsce znaku dolara.
Przykład użycia makra sequence:
Makro wygeneruje:

Makro foreach-elem:

{foreach-elem lista} treść {/} - Makro foreach-elem podstawia kolejne elementy z listy. Lista musi zawierać wartości liczbowe lub tekstowe, oddzielone białymi znakami (spacja, tabulator). Kolejne elementy wstawiane są w miejsce znaku dolara.
Przykład użycia makra foreach-elem:
Makro wygeneruje:

Makro foreach-pair:

{foreach-pair lista_par} treść {/} - Makro foreach-pair podstawia kolejne pary elementów z listy. Lista musi zawierać pary wartości liczbowych lub tekstowych. Pary elementów oddzielone są od siebie przecinkami, elementy pary białymi znakami (spacja, tabulator). Pierwszy element pary to klucz, wstawiany jest w miejsce znaku procenta. Drugi element pary wstawiany jest w miejsce znaku dolara.
Przykład użycia makra foreach-pair:
Makro wygeneruje:

Obsługa markowania pakietów

Markowanie pakietów to zabieg przypisania pakietom wirtualnego znacznika, dzięki któremu, np. po wykonaniu zabiegu SNAT-owania (maskarada IP), ciągle możliwe jest rozpoznanie ich nadawców pomimo zmienionych adresów źródłowych. Wartość ta przyporządkowywana jest przez iptables, pamiętana przez kernel Linuksa i rozpoznawana przez filtr kernela typu FW. Filtr kernela FW przyporządkowuje pakiety do kolejek HTB, w przeciwieństwie do filtra U32, nie za pomocą testów na nagłówkach a na podstawie tego wirtualnego znacznika.

Najczęściej markowanie pakietów nie wymaga patchowania iptables ani kernela. Sam NiceShaper zarządza całością całkowicie automatycznie. Jest to mechanizm bardzo łatwy w uruchomieniu, dlatego markowanie pakietów to dobry sposób na obsługę ruchu wychodzące generowanego przez stacje robocze z prywatnymi adresami IP, bez użycia również wygodnych, ale wymagających patchowania tych ważnych składników Systemu Operacyjnego interfejsów IMQ.

Tak więc, jeśli na danym interfejsie poprzez dyrektywę mark-on-ifaces włączone zostanie markowanie pakietów, NiceShaper każdej klasie pracującej na tym interfejsie przyporządkuje niepowtarzalną wartość znacznika a typ filtrów kernela na danym interfejsie, zostanie zamieniony z U32 na FW. Wszystko to odbywa się w pełni automatycznie. Jeśli jednak z jakiegoś powodu zajdzie taka potrzeba, można wskazać oczekiwaną wartość znacznika klasy, służy temu parametr klasy set-mark. Wskazana w ten sposób wartość nie może powtórzyć się w innej klasie.

Iptables a więc i NiceShaper akceptuje wartości znaczników z zakresu od 0 do 4294967295 (wartość 32bitowa), podawane w formie dziesiętnej lub szesnastkowej poprzedzonej znakami 0x.

Obsługa interfejsów IMQ

NiceShaper obsługuje IMQ, skompilowane w trybie AB (za NATem w PREROUTINGu, przed NATem w POSTROUTINGu).

Od strony konfiguracji NiceShapera, interfejsów IMQ używa się analogicznie jak tych fizycznych. Prawie zapomnieć można o ich wirtualności, z pełną swobodą mieszając klasy pracujące na interfejsach fizycznych oraz IMQ.

Filtry wymagają wskazania interfejsu fizycznego poprzez test out-iface (lub in-iface jeśli wartość iptables hook zmieniono na PREROUTING).

Przykładowy wycinek pliku class.conf:

NiceShaper automatycznie przekierowuje ruch na interfejsy IMQ a zachowanie to w razie potrzeby, konfigurowalne jest z poziomu dyrektywy globalnej iptables imq-autoredirect. W przypadku wyłączenia automatycznego przekierowania na IMQ -co nie jest zalecane- należy takowe wykonać dla NiceShapera, czyli: iptables ... -j IMQ --todev ...

Wyzwalacze

Wyzwalacze są mechanizmem umożliwiającym automatyczną zmianę wartości niektórych parametrów klasy po zaistnieniu zdefiniowanego zdarzenia. W aktualnej wersji NiceShapera zaimplementowane są 2 wyzwalacze - alter oraz quota.

Sterowane parametry klasy:

Sterujące parametry wyzwalaczy:

Wyzwalacze są dyrektywą klas, najwygodniej zdefiniować je w ramach sekcji, np.:
Wyzwalacz quota ma wyższy priorytet od wyzwalacza alter, więc jeśli dla któregoś parametru sterowanego nastąpią warunki zadziałania w obydwu wyzwalaczach, użyty zostanie parametr z wyzwalacza quota. Wyzwalacze działają wyłącznie dla klas typu standard-class. Wartości liczników wyzwalacza quota pomiędzy uruchomieniami programu przechowywane są w plikach nazwa_sekcji.quota w katalogu /var/lib/niceshaper. Pliki te uaktualniane są w momencie wyłączania NiceShapera oraz w trakcie jego pracy w odstępach 5 minutowych. W przypadku niepowodzenia zapisu tych plików, stan liczników zostanie bezpowrotnie utracony!

Jak traktować ruch z i do routera

Ruch pobierany i wysyłany przez sam router najczęściej jest pomijalnie mały i nie wymaga kontroli. Jednak w praktyce, router z Linuksem często udostępnia zasoby plikowe w sieci lokalnej (prostszy scenariusz), a nawet pełni dodatkowe role serwera usługowego (trudniejszy scenariusz).

Ze względu na to, że kształtowanie ruchu odbywa się, na interfejsie którym pakiety opuszczają router, kontrola ruchu przychodzącego (zarówno do strony Internetu jak i LANu) jest utrudniona i wymaga wykorzystania interfejsów IMQ.

By praktycznie rozpatrzyć ten temat, najwygodniejsze będzie rozbicie zagadnienia na 4 scenariusze.

We wszystkich przypadkach należy dodać do filtrów odpowiedni test from-local lub to-local. W przypadkach z interfejsami IMQ pojawia się, dodatkowy, wymagany test in-iface. Ewentualnie out-iface dla ruchu wychodzącego. Wymóg użycia tego testu istnieje, by filtry iptables przekierowywały na interfejsy IMQ, pakiety, jeśli są one dopasowane filtrem oraz interfejsem fizycznym - zapewniając rozróżnienie ruchu po stronie WAN od ruchu po stronie LAN.

Należy pamiętać, że najczęściej klasy tego typu powinny znajdować się na samym początku listy klas.

Przypomnijmy, że łącze internetowe podłączone jest do interfejsu eth0, sieć LAN do eth1. Adres publiczny routera to 198.51.100.100, a dodatkowy adres dla usług to 198.51.100.101, adres prywatny to 192.168.0.1, a adresacja sieci lokalnej to 192.168.0.0/24.

Wymiana ruchu routera z siecią lokalną (nie angażuje pasma łącza).

Kontrola pasma pomiędzy routerem a siecią lokalną, wymaga, wyłączenia z ograniczania. Przecież nie należy ograniczać, nie obciążających łącza transmisji po wydajnym LANowym ethernecie. Ba, dużym błędem byłoby zaliczenie ich do klas klientów, jeśli pobieranie zasobów z serwera plików nie obciąża pasma internetowego. Dla scenariuszy 1 i 2 czyli ruchu między routerem a siecią lokalną, należy używać wyłącznie klas typów wrapper lub do-not-shape.
Klasy typów wrapper i do-not-shape nie należą do sekcji, dlatego ich nagłówek różni się od nagłówka klasy standardowej:
class-wrapper|class-do-not-shape interfejs nazwa

1. Router -> Localnet - Router wysyła dane do sieci lokalnej.

Ruch opisywany w tym scenariuszu to, np. lokalny serwer plików samba lub ftp, serwery poczty imap czy pop3 itp.

Opcja klasy typu do-not-shape - transfery są lokalne więc nie tniemy i nie wliczamy do sumarycznego wykorzystania łącza:

Opcja klasy typu wrapper - transfery są lokalne, ale w sieci LAN mamy link o niższej wydajności (np. typu WiFi.). Ograniczamy, ale za pomocą statycznie przydzielonego pasma i konsekwentnie bez wliczania tego ruchu do wykorzystania łącza:

2. Router <- Localnet - Router odbiera dane z sieci lokalnej.

Ruch z sieci lokalnej do routera. Np. umieszczanie zasobów na lokalnym serwerze plików, wysyłanie poczty za pomocą lokalnego serwera smtp itp.

Opcja klasy typu do-not-shape - Na poziomie iptables NiceShaper używa łańcucha POSTROUTING a na poziomie QOS ingress shaping nie jest używany. Stąd nie ma potrzeby tworzenia klasy typu do-not-shape, gdyż ruch opisywany przez ten scenariusz, ze wskazanych powodów, jest domyślnie całkowicie pomijany.

Opcja klasy typu wrapper - jeśli jednak, analogicznie jak w scenariuszu nr. 1, chcemy użyć klasy typu wrapper, uzyskanie kontroli nad pasmem przychodzącym do routera wymaga użycia interfejsów typu IMQ.

Wymiana ruchu routera z internetem (angażuje pasmo łącza).

Serwowanie usług przez router, po stronie WAN, nie powinno być nadużywane. Jeśli jednocześnie używany jest SNAT lokalnych hostów, usługi dostępne od strony internetu powinny być uruchomione na niezależnym od SNAT publicznym adresie IP. Wymóg posiadania przynajmniej 2-ch publicznych adresów IP (niezależny adres dla SNAT i niezależny adres dla usług), jest wymuszona tym, że w łańcuchu PREROUTING tabeli mangle nie ma możliwości odróżnienia ruchu skierowanego do routera od ruchu NATowanego. W łańcuchu INPUT gdzie odróżnienie jest możliwe (upraszczając), nie ma już jednak możliwości przekierowania ruchu na interfejs IMQ a ten jest niezbędny do kontrolowania ruchu przychodzącego.

3. Router -> Internet - Router wysyła dane do internetu.

Obsługa, na przykład, uruchomionych na routerze serwerów www czy poczty, wysyłających dane w stronę internetu.

W poniższym przykładzie, w przeciwieństwie do scenariuszów 1 i 2, utworzono dwie osobne klasy, by odseparować pasma różnych usług.

Umieszczenie klas w sekcji pracującej w trybie upload i filtrowanie testem from-local, nie wymagają szerszego komentarza. Parametry te dają pewność, że ruch wysyłany przez router do internetu, będzie właściwie zliczany.

4. Router <- Internet - Router odbiera dane z internetu.

Ruch z internetu do routera, np. witryny www pobierane przez serwer proxy, czy aktualizacje systemu operacyjnego routera mogące zabierać pasmo klientom.
Umieszczenie klasy w sekcji pracującej w trybie download i filtrowanie testem to-local, znów, nie wymaga szerszego komentarza - jest oczywiste.

Domyślnie, dla klas pracujących w trybie download, filtry iptables tworzone są w łańcuchu do którego ruch przekierowywany jest z POSTROUTINGu. Obsługiwany w tym scenariuszu ruch, nigdy się tam nie pojawia. Stąd, użycie testu to-local, powoduje utworzenie dodatkowego filtra w łańcuchu PREROUTING.

Tematy zaawansowane

Współpraca z iptables

Jak już zaznaczono, NiceShaper w kilku sytuacjach wymaga programu iptables. Startując, umieszcza swoje reguły w tabeli mangle a usuwa je przy wyjściu. Zaleca się, by jeśli to możliwe, unikać tych sytuacji. Reguły iptables dla dużej liczby klas będą generować dodatkowe obciążenie. Niestety, jeśli choć jedna z klas w sekcji NiceShapera wymaga reguły w iptables, wprowadzone zostaną reguły dla wszystkich klas tej sekcji, nawet jeśli nie będą wykorzystywane. Ale co gorsza, także dla wszystkich klas innych sekcji tego samego trybu, jeśli występują (tryb sekcji konfigurowany jest za pomocą dyrektywy mode i przyjmuje wartość download lub upload).

Precyzyjniej reguły iptables są potrzebne, więc i tworzone, do wykonywania następujących zadań:

Jeśli kilka sekcji współdzieli jeden łańcuch iptables, wykorzystywany będzie cache zapełniony podczas poprzedniego odczytu. Czas ważności zawartości cache ustalono na 0.1 sekundy, więc odczyt liczników żadnego z łańcuchów nie wystąpi częściej.

NiceShaper aż do wersji 1.0 wykorzystywał reguły w iptables, jako fundamentalny element swojej pracy. Reguły były tworzone zawsze i dla wszystkich zdefiniowanych klas a służyły zarówno do wykrywania aktywności jak i zliczania generowanego przez nie ruchu. Od wersji 1.2pre1, reguły iptables jedynie wspomagają NiceShapera.

Współpraca z HTB

Na każdym z kontrolowanych interfejsów, tworzona jest, zaprezentowana na poniższym diagramie struktura elementów QOS. Struktura ta składa się z kolejek HTB, algorytmów kolejkowania i filtrów kernela. Kolejki HTB tworzą drzewiastą hierarchię, przez którą ruch jest propagowany, tak jak przedstawiono.

NiceShaper nie używa programu tc. Komunikuje się, za pomocą protokołu Netlink, bezpośrednio z kernelem Linuksa - kod odpowiedzialny za tą komunikację częściowo bazuje na kodzie iproute. Jest to najwydajniejsza metoda zarządzania obiektami QOS.

HTB Diagram
Na najniższym poziomie przepustowość interfejsu dzielona jest, na kolejki HTB o stałych i równych sobie wartościach parametrów rate i ceil. Te kolejki HTB nie dzielą się niewykorzystaną przepustowością.

Spełniają one trzy role:

1) Każda sekcja działająca na interfejsie (liczba sekcji nie jest ograniczona do jednej), otrzymuje kolejkę HTB o przepustowości równej wartości parametru section speed. Kolejka ta zostaje kolejką nadrzędną, dla wszystkich kolejek klas wchodzących w skład tej sekcji. Jedna z kolejek podrzędnych zostaje utworzona automatycznie, jest to tzw. poczekalnia (Waiting Room), Ruch sklasyfikowany za pomocą filtrów kernela trafia w pierwszej kolejności do tej klasy. Następnie przy przeładowaniu tworzona jest kolejka HTB dla odpowiedniej klasy NiceShapera a filtry kernela zostają tak zmodyfikowane by w efekcie ruch trafiał do docelowej kolejki HTB klasy NiceShapera i za jej pomocą był kontrolowany. Po ustalonym parametrem hold czasie nieaktywności, klasa zostaje usunięta a filtry kernela ponownie przekazują ruch do kolejki poczekalni. Dzięki temu mechanizmowi w tym samym czasie w HTB występują kolejki tylko aktywnych klas NiceShapera, co daje optymalne wartości parametru rate kolejek HTB.

2) Kolejka HTB nadrzędna dla klas typu do-not-shape oraz wrapper, jest kolejką mającą swoją rolę gdy na interfejsie działają klasy jednego lub obydwu z tych typów. W przypadku klas do-not-shape tylko w połączeniu z opcją iface do-not-shape-method safe. Jeśli żadna z tych sytuacji nie występuje, ta kolejka HTB w ogóle nie zostaje utworzona. Jej przepustowość jest przepustowością pozostałą po rozdzieleniu przepustowości interfejsu (iface speed), pomiędzy kolejki sekcji oraz kolejkę awaryjną (patrz 3).

3) Kolejka awaryjna przejmuje cały niesklasyfikowany ruch wychodzący z interfejsu. By podział łącza mógł działać poprawnie do tej kolejki nie powinno nigdy nic wpadać. Jeśli ten warunek nie zostaje spełniony, należy odszukać braki w zdefiniowanych klasach i filtrach. Aż do wersji 1.0pre3 cały niesklasyfikowany przez utworzone filtry ruch, zostawał skolejkowany z pełną prędkością interfejsu. Utrudniało to poprawne działanie podziału. Jednak przywrócenie tego sposobu zachowania jest możliwe, umożliwia je odpowiednia opcja dyrektywy iface. W tym przypadku awaryjna kolejka HTB w ogóle nie zostanie utworzona. Od wersji 1.0pre4 niesklasyfikowany ruch próbujący opuścić kontrolowany interfejs musi przejść przez kolejkę awaryjną o bardzo niskiej przepustowości.