Co přesněji máme dnes v plánu?

Vysvětlení principu shapingu

Cílem shapování je nějaká úprava trafficu. Většinou se snažíme ladit jak příchozí (download), tak i odchozí (upload) traffic. Každý myslí na ladění příchozího trafficu a na odchozí se občas zapomene. Proč by se měl člověk zabývat nějakým odchozím provozem, když chce jen dobře stahovat. Ne každý si uvědomuje, že i odchozí provoz má celkem velký vliv na kvalitu celého pásma.

Shapování příchozího provozu se provádí na rozhraní, které směřuje do vnitřní (lokální) sítě (LAN). Upload se ladí na rozhraní, které směřuje do internetu nebo do nějaké jiné vnější sítě (WAN). Vždy prostě nastavíme pravidla s filtry na to rozhraní, které posílá později shapovaná data.

traffic shaping 2 schema

Tak, teď asi dost lidí napadají otázky typu: no jo, ale co když nemá router dvě síťová rozhraní, ale jen jedno, které vede přímo do internetu? Nebo naopak rozhraní přebývají. Kam se potom nastaví pravidla pro příslušný shaping?

traffic shaping 2 schema traffic shaping 2 schema

Není mnoho možností, jak tyto situace řešit, jedno si však ukážeme.

IMQ

Jak už padlo v předchozím článku, imq je virtuální síťové rozhraní, kam se přesměruje síťový provoz, který chceme shapovat. Děláme tak z několika důvodů. Hlavním je třeba chybějící rozhraní, na kterém bychom prováděli shapování. Dalším je potom přebývající rozhraní. V neposlední řadě umožňuje lehký shaping s NATem. Nevýhodou imq je to, že provádí nečisté věcičky, a proto ho asi nikdy nenajdeme oficiálně v kernelu - a musíme patchovat. Také jeho stabilita bývala někdy sporná. Mně osobně mi jednou vytuhl PC. To ovšem nebylo za klasického provozu, ale laboroval jsem s imq, co to dá. Pokud si nějaké nastavení odzkoušíte, a nebudete provádět testy při ostrém provozu, tak pochybuji, že vám imq způsobí potíže.

IMQ: nastavení modulu a kernelu

Základem je mít opatchované jádro a iptables, což můžeme zhotovit podle minulého článku. Jako výchozí bývá v jádře nastaven počet rozhraní na dvě, takže když provedete načtení modulu bez parametrů

modprobe imq

tak se nám vytvoří dvě imq zařízení (imq0 a imq1)

ip link
...
  11: imq0: <NOARP> mtu 1500 qdisc noop qlen 30
     link/void
  12: imq1: <NOARP> mtu 1500 qdisc noop qlen 30
     link/void
...

Počet virtuálních imq zařízení můžeme také ovlivnit parametrem při připojování modulu (pro vytvoření jednoho imq zařízení):

modprobe imq numdevs=1

Další věcí, která bývá v jádře nastavena, je schéma zapojení imq v jednotlivých tabulkách před NATem či za ním. Tuto důležitou skutečnost jsem v předchozím článku nezmínil, tak jí teď zařadím.

Imq může být nastaveno takto (zakřížkovaná položka je výchozí nastavení):

Device Drivers -->
   Network device support  --->
      <M> IMQ (intermediate queueing device) support
          IMQ behavior (PRE/POSTROUTING) (IMQ BA) --->

		( ) IMQ AA
		( ) IMQ AB
		(X) IMQ BA
		( ) IMQ BB
         (2)   Number of IMQ devices 

Význam jednotlivých zkratek :

První písmeno značí nastavení v tabulce PREROUTING a druhé v POSTROUTING:

A = after (po) => imq projde paket až po natu
B = before (před) => imq projde paket před natem

Pro změnu schématu stačí jen přenastavit .config a překompilovat modul imq:

make menuconfig
make
make modules_install
rmmod imq
modprobe imq

Typ schématu potom můžeme vidět ve výpisu dmesg hned po připojení modulu imq.

Než si zvolíme schéma sobě blízké, musíme nejprve vědět, jak paket vůbec cestuje netfilterem.

Cesta paketu

Vše by mělo znázorňovat následující schéma. Jen upozorním, že toto zdaleka není kompletní schéma, ale pro naše potřeby postačí.

traffic shaping 2 schema

Paket postupně prochází přes PREROUTING. Zde a nikde jinde probíhá změna adresy na adresu příjemce (DNAT). Pak dorazí na rozhodovák. Pokud má paket IP routeru, tak vleze přes chain INPUT k lokálním procesům na serveru. Odtud dále přes chain OUTPUT, který lze použít k DNATování paketů vzniklých pouze na lokálním počítači. Pokud paket nenáleží routeru, tak jde přes chain FORWARD. Všechny pakety potom odcházejí přes POSTROUTING, kde mohou být SNATovány (změní se zdrojová IP adresa za cílovou => IP adresy, na které je aplikován SNAT, budou mít IP adresu stejnou jako má router). Toto schéma se aplikuje na každé rozhraní.

Velice jednoduchý obrázek níže by snad mohl pomoci k porozumění. PREROUTING je první věc, kterou paket potká, když vyleze z rozhraní. POSTROUTING je poslední věc, kterou paket proleze. Zelené kolečko značí vstup do "magické iptables tabulky (router)" a červené zase výstup. (Velice jednoduše a nepřesně řečeno, snad mi znalí uživatelé odpustí.) Když jsem přemítal, na co aplikovat filtry pro download apod., tak mi tento obrázek velice pomohl.

traffic shaping 2 schema

Tak, teď jistě chápete, proč je zvolený typ schématu velice důležitý.

Pokud tedy používáte SNAT/maškarádu, tak by bylo asi nejlepší, kdybyste si zvolili typ AB. Paket přiletí do PREROUTINGu, tam NAT převede IP na zdrojovou a potom se aplikuje imq - takže potom ve filtru pracujeme se zdrojovými adresami a jsme za vodou. Když chceme aplikovat shapovací skript na upload, tak imq umístíme do POSTROUTINGu před (before) NAT.

Když používáme klasický SNAT/maškarádu, tak nemusíme aplikovat imq na PREROUTING s tím, že shapovací skript hodíme přímo na rozhraní do LANu. To má ovšem jeden malinkatý háček/výhodu/nevýhodu. Takový skript nám neumožní shapovat lokální traffic na routeru, protože se filtr aplikuje až někde u POSTROUTINGu na rozhraní do LAN a tudy lokální provoz na serveru neprotéká.

Finální řešení pomocí imq

Tak, dost teorie a jdeme konečně něco nahodit. Nejprve se podíváme k problému s chybějícími rozhraními. Do vytvořeného virtuálního imq0 přesměrujeme traffic, který proudí z internetu k nám (eth0 = WAN; eth1 = LAN).

iptables -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0

Kde číslo za --todev značí očíslované imq, v našem případě imq0.

Teď, když máme přesměrovaný provoz z internetu přes naše imq, tak můžeme celé virtuální imq rozhraní nahodit:

ip link set imq0 up

Když si pak spustíte např. nějaké stahování z internetu, tak byste měli vidět, jak přes imq0 cestují pakety. To zjistíte např. příkazem:

ifconfig
....
Zapouzdření:NEZNÁM HWadr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
AKTIVOVÁNO BĚŽÍ NEARP MTU:1500 Metrika:1
RX packets:879774 errors:0 dropped:0 overruns:0 frame:0
TX packets:879338 errors:0 dropped:0 overruns:0 carrier:0
kolizí:0 délka odchozí fronty:30
RX bytes:369590578 (352.4 MiB) TX bytes:369321146 (352.2 MiB)
...

Pozor - když se na něj zkusíte podívat s tcpdumpem pomocí:

tcpdump -i imq0

tak nic neukáže.

Celé naše snažení by pak mělo vypadat nějak takto :

traffic shaping 2 schema

Druhý příklad je o dva řádky delší (eth0 = WAN; eth1, eth2, eth3 = LAN):

iptables -t mangle -A POSTROUTING -o eth1 -j IMQ --todev 0
iptables -t mangle -A POSTROUTING -o eth2 -j IMQ --todev 0
iptables -t mangle -A POSTROUTING -o eth3 -j IMQ --todev 0
ip link set imq0 up

Tímto jsme vlastně přesměrovali veškerý odchozí provoz do LANu přes imq. Shapování downloadu by teď měla být hračka.

traffic shaping 2 schema

Vnímavější by možná napadlo hodit na LAN 1, 2 a 3 bridge br0. Tím by se vytvořilo jedno virtuální zařízení, které by dokonce umožňovalo, aby byly všechny podsítě ve stejném rozsahu. Je to velice dobrý nápad, avšak má jednu drobnou chybku. Na br0 se nedá provádět shapování, protože iptables na něj neplatí (i když někdo tvrdí, že mu to iptables dokáže) a je k dispozici pro konfiguraci balíček ebtables. Takže pokud má někdo nakonfigurovaný bridge, tak bude stejně asi muset sáhnout po imq.

IMQ a oba směry

Jak vidíte, tak do imq zařízení se dá přesměrovat více než jeden provoz. IMQ zařízením nemusí být přesměrován jen jednosměrný provoz, můžete do něj přesměrovat jak odchozí, tak příchozí traffic:

iptables -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0
iptables -t mangle -A POSTROUTING -o eth0 -j IMQ --todev 0
ip link set imq0 up

Nyní můžeme na jednom imq zařízení shapovat jak download, tak upload.

traffic shaping 2 schema

Rekapitulace

Co nám ten dnešek nakonec dal?:

Dodatek:

IMQ lze umístit např. i do chainu FORWARD. Na druhou stranu nelze provozovat více imq zařízení v jednom směru. Pokud tak učiníme, bude fungovat poslední vytvořené.

Závěr

Tak, snad jsem vše vysvětlil dostatečně a příště se zase na něco podíváme :).