PLD i kilka łącz (routing wielobramowy)
Jakiś, spory już czas temu stanąłem przed zadaniem konfiguracji load-balance'ingu w oparciu o moje ulubione PLD Linux pomiędzy kilkoma łączami zewnętrznymi. Po przeszukaniu sieci prawdę powiedziawszy, nie znalazłem kompleksowego HOW-TO. Może po prostu przeoczyłem, nie mniej jednak dziś postaram się opisać sposób w który ja rozwiązałem powyższy problem
Trochę teorii.
Największą bolączką powszechnie dostępnych tanich łącz klasy TPSA Internet DSL jest ich niesymetryczność. Jeśli cały ruch z wewnętrznej sieci puścimy przez niesymetryczne łącze, to nawet pomimo stosowania QOS istnieje duże prawdopodobieństwo, że użytkownicy programów p2p szybko zapchają upload, co skutkuje skutecznymi opóźnieniami na łączu niezależnymi od wysycenia downloadu. Warto zauważyć również, iż zwykły użytkownik relatywną prędkość jego łącza ocenia poprzez jakość działania najpopularniejszych usług takich jak poczta czy WWW. Interesującym zatem, z punktu widzenia jakości usługi jest priorytetyzacja/izolacja pewnych usług, które mają bezpośredni wpływ na zadowolenie klientów z posiadanego łącza.
Założenia:
- trzy lub więcej łącz zewnętrznych (InternetDSL)
- PLD Linux 2.4 jako NAT+HTB. Kernel 2.4 jest z mojego doświadczenia stabilny dla proponowanego rozwiązania. Z kernelami 2.6 nie udało mi się tego uruchomić (być może to jakiś PLD specyfic) nie mniej jednak powszechnie znane są problemy dla tego kernela z HTB.
- dwie wewnętrzne klasy adresowe
Rozważmy taki układ:
- eth0, ip: 80.0.0.2, gw: 80.0.0.1: ruch domyślny dla klasy 192.168.1.0/24
- eth1, ip: 80.0.1.2, gw: 80.0.1.1: ruch domyślny dla klasy 192.168.2.0/24
- eth2, ip: 80.0.2.2, gw: 80.0.2.1: łącze na wyizolowane usługi dla obu klas
- eth3, ip: 192.168.1.254: klasa adresowa wewnętrzna
- eth4, ip: 192.168.2.254: klasa adresowa wewnętrzna
Poprzez ruch domyślny rozumiem wszystkie, nie oznaczone specjalnie pakiety, ruch izolowany to WWW, POP3, SMTP
Implementacja:
Poniższa implementacja jest słuszna właściwie dla każdego systemu wspierającego iproute2 i iptables. Konfigurujemy standardowo 5 interfejsów sieciowych przypisując im właściwe adresy. Nie definiujemy w pliku /etc/sysconfig/network bramy ustawiając parametry na:
GATEWAY="" GATEWAYDEV=""
Zestaw magicznych komend do skonfigurowania ręcznego routingu.
Przypisujemy kazde łacze do osobnej tablicy routingu:
ip route add default via 80.0.0.1 table 10 ip route add 192.168.1.0/24 via 192.168.1.254 table 10 ip route add 192.168.2.0/24 via 192.168.2.254 table 10 ip route add default via 80.0.1.1 table 20 ip route add 192.168.1.0/24 via 192.168.1.254 table 20 ip route add 192.168.2.0/24 via 192.168.2.254 table 20 ip route add default via 80.0.3.1 table 30 ip route add 192.168.1.0/24 via 192.168.1.254 table 30 ip route add 192.168.2.0/24 via 192.168.2.254 table 30
Następnie definiujemy która klasa powinna być routowana przez którą tablicę, przez 10 i 20 puszczamy ruch w całości per klasa adresowa, przez 30 tylko ruch znaczony:
ip rule add from 192.168.1.0/24 table 10 ip rule add from 192.168.2.0/24 table 20 ip rule add from 192.168.1.0/24 fwmark 0x41 table 30 ip rule add from 192.168.2.0/24 fwmark 0x42 table 30 ip rule add from 80.0.0.2 table 10 ip rule add from 80.0.2.2 table 20 ip rule add from 80.0.3.2 table 30
Definiujemy routing prywatny: domyślna brama, używając wszystkich łącz. Używane będzie dowolne dostępne (wszystko jako jedna komenda):
ip route add default scope global nexthop via 80.0.0.1 dev eth0 weight 1 nexthop via 80.0.1.1 dev eth1 weight 1 nexthop via 80.0.2.1 dev eth2 weight 1
Tyle z routingiem, komendy można wpisać do własnego skryptu uruchamianego zaraz po podniesieniu interfejsów sieciowych lub po prostu do rc.local
Dalej konfiguracja /proc Opcję rp_filter trzeba ustawić na 0 i uaktywnić ip_forward:
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo "0" > $f; done sysctl -n -e -w net.ipv4.conf.all.rp_filter="0" sysctl -n -e -w net.ipv4.ip_forward="1"
Jak wyżej, warto to wpisać razem z komendami konfigurującymi routing.
Teraz iptables:
Standardowo NAT:
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to 80.0.0.2 iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j SNAT --to 80.0.0.2 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j SNAT --to 80.0.1.2 iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth1 -j SNAT --to 80.0.1.2 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth2 -j SNAT --to 80.0.2.2 iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth2 -j SNAT --to 80.0.2.2
I znaczymy pakiety które mają iść izolowanym łączem (wcięcie linii to kontunuacja poprzedniej):
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark iptables -t mangle -A PREROUTING -i eth3 -p tcp -m mport --dports 25,80,110,443 -j MARK --set-mark 0x41 iptables -t mangle -A PREROUTING -i eth4 -p tcp -m mport --dports 25,80,110,443 -j MARK --set-mark 0x42 iptables -t mangle -A PREROUTING -m mark ! --mark 0x0 -j RETURN
I tyle.
Jak łatwo zauważyć konfiguracja jest nadmiarowa (np nie trzeba NATować wszystkich klas) ale w przypadku awarii np łącza 80.0.1.2 możemy szybko przełączyć cały ruch na łącze 80.0.0.2 puszczając go przez tablicę 10:
ip rule add from 192.168.2.0/24 table 20 -> ip rule add from 192.168.2.0/24 table 10
Pakiety można znaczyć (mark) wg dowolnych reguł, np. adresu docelowego, dla serwerów gier czy np. GG, adresu źródłowego: można wyizolować ruch dla poszczególnych klientów. Pewnym rozwiązaniem może być także przypisanie do każdej z tablic znacznika (tak jak dla tablicy 30) i znaczenie via iptables całego ruchu. Z doświadczenia: problematycznym jest znaczenie pakietów p2p przez moduł ipp2p ponieważ nie klasyfikuje on wszystkich pakietów poprawnie i występują problemy. Ruch p2p lepiej zostawić nieoznaczony i puścić domyślnym łączem. Nie pokusiłem się również o priorytetyzację VoIP czy eg. Skype. Można do tego użyć modułu Layer7 (??) niedostępnego standardowo w PLD.
Przypuszczalnie całość można, a nawet trzebaby zrobić "koszerniej", routing do /etc/sysconfig/static-routes /etc/sysconfig/static-rules, konfig /proc do /etc/sysctrl, iptables via jakaś nakładka. Wszystkie udoskonalenia mile widziane w komentarzach.






2 Responses to “PLD i kilka łącz (routing wielobramowy)”
By Wiktor on gru 14, 2007
Do poprawienia:
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo “0″ > $f; done
sysctl -n -e -q -w net.ipv4.conf.all.rp_filter=”0″
sysctl -n -e -q -w net.ipv4.ip_forward=”1″
PS: no cóż, pewnie jak bym opublikował swoje rozwiązanie (tak z roku 2005), to miałbyś gotowca.
By Arek Kuryłowicz on gru 15, 2007
Święta racja, zeżarło końcówkę linii przy edycji, oczywiście bez twojej korekty powyższa składnia nie miała prawa działać.