[OT] Dwa łącza i routing

Bohdan R. Rau ethanak w polip.com
Nie, 16 Sty 2005, 10:39:38 CET


Michal Koziorowski wrote:

>
> A czy moglbys jeszcze wyslac konfiguracje nata iptables do obslugi 
> takiego ruchu?. Nie mam takich lacz ale temat wydaje mi sie ciekawy i 
> chcialem sobie zachowac cala dyskusje na przyszlosc.
>
Przepraszam że dopiero teraz ale miałem trochę mało czasu - poza tym w 
rzeczywistości wszystko u mnie jest generowane przez taki fikuśny 
programik w C ściągający dane klientów z postgresa i musiałem jakoś to 
przystosować...

A więc:
Sieć: ok 300 klientów, podłączeni radyjkiem. Aktualnie: 5 x 2 MBit DSL 
(4x dialog, 1x tpsa), docelowo jeszcze dwie tepsy.

Router to P4 2.4 GHz, 512 MB RAM, dysk jakiś szybszy SCSI, kontroler 
Adaptec Ultra320. Dwie czteroportowe sieciówki D-Link (nie pamiętam 
typu, zgłaszają się jako D-Link DL10050 Sundance Ethernet). Dla 
przypomnienia: PLD Ra, 2.4.26 + patch

Zainstalowane dodatkowo: squid, dnsmasq. Programik na QUEUE ogranicza 
ilość jednoczesnych połączeń danego klienta (nie tak jak connlimit, bo 
traktuje jako połączenie każdy pakiet wysłany gdziekolwiek - niezależnie 
od tego czy połączenie zostało w rzeczywistości nawiązane - i pamięta 
taki fakt przez ileś tam sekund) do 8 różnych hostów (dobrane 
empirycznie). Bardzo wspaniale sobie radzi z wszelakim robactwem, 
panoszącymi się wirusami oraz genialnymi klientami próbującymi swoich 
sił w skanowaniu sieci. Źródełka w razie potrzeby mogę udostępnić.

A więc zaczynamy...

1) iptables

Dla każdej podsieci klienckiej mam:

#magiczny program ogranicznika połączeń
iptables -A PREROUTING -t mangle -s $siec -j QUEUE

#transparent squid
iptables -t nat -A PREROUTING -p tcp -s $siec \
-d '!' $moje_serwery \
--dport 80 -j REDIRECT --to-port 3128

#dnsmasq - jako że nieprzewidywalnym jest co klient wpisze
# w konfiguracji DNS-ów
iptables -t nat -A PREROUTING -p udp -s $siec \
--dport 53 -j REDIRECT --to-port 53

# i kolejno dla wszystkich interfejsów wyjściowych:
iptables -A POSTROUTING -t nat -o $interface -s $siec \
-d '!' $moje_serwery -j SNAT --to-source $ifaddr

#teraz dla każdego "swobodnego" adresu z sieci klienckich
#coby się obce elementy nie podłączały:

iptables -I PREROUTING -t mangle -s $adres -d 0/0 -j DROP

#a dla każdego klienta (jako że nie mogę stosować IMQ)
iptables -A POSTROUTING -t mangle -s $adres -j MARK \
--set-mark $numer_klienta

2) routing

Dla kazdego interfejsu jest oczywiscie oddzielna tabela.
Jako że maszyna ma oddzielny interfejs na futuro (dla klientów z 
zewnętrznymi IP i takich tam podobnych) mamy tu dodatkową tabelę futuro. 
Czyli:

#dla każdego interfejsu wyjściowego:
ip rule add from $ifaddr table $tabela
ip route add 0/0 via $gateway table $tabela


#serwery na lokalnym ethernecie - podłączone przez inny router (10.0.0.1 
- mój adres to 10.0.0.2)
ip route add to $moje_serwery via 10.0.0.2

#wyjście na świat przez futuro
ip route add 0/0 via 10.0.0.1 table futuro

#klienci zewwnętrzni
ip rule add from $siec_klientow table futuro

#dns-y futuro
ip rule add to 62.233.128.18 table futuro
ip rule add to 62.233.128.17 table futuro
ip rule add to 213.77.129.149 table futuro

#z dziwnych przyczyn router nie widzi klientów - tak jakby nie 
uwzględniał local. W związku z tym mam lokalną tablicę i na chama dla 
każdej sieci mu wpisuję co gdzie ma routować

ip route add $siec via $interfejs table lokalna
ip rule add to $siec table lokalna

#no i najważniejsze - wyjście na świat:
ip route add 0/0 proto static \
nexthop via $gateway1 dev $if1 \
nexthop via $gateway2 dev $if2 \
nexthop via $gateway3 dev $if3 \
nexthop via $gateway4 dev $if4 \
nexthop via $gateway5 dev $if5

3) limity na interfejsach:

tc qdisc add dev $interface root handle 1: htb default 20
tc class add dev $interface parent 1: classid 1:1 htb \
    rate 440kbit burst 12k

tc class add dev $interface parent 1:1 classid 1:10 htb \
    rate 440kbit burst 12k prio 1

tc class add dev $interface parent 1:1 classid 1:20 htb \
rate 396kbit burst 12k prio 2

tc qdisc add dev $interface parent 1:10 handle 10: sfq
tc qdisc add dev $interface parent 1:20 handle 20: sfq

tc filter add dev $interface parent 1: protocol ip prio 10 u32 \
     match ip protocol 6 0xff match u8 0x05 0x0f at 0 \
        match u16 0x0000 0xffc0 at 2 \
        match u8 0x10 0xff at 33 \
        flowid 1:10

tc qdisc add dev $interface handle ffff: ingress

tc filter add dev $interface parent ffff: protocol ip prio 50 u32 \
    match ip src 0.0.0.0/0 police rate 1638kbit burst 10k drop \
    flowid :1

#teraz dla każdego klienta mam trzy cyferki:
# $numer - numer klienta (taki jak w MARK)
# $klasa - unikalna klasa
# $uchwyt - unikalny uchwyt
# u mnie jest to tak, że kolejne numerki różnią się o 2,
# klasa jest równa numerkowi, a uchwyt to klasa+1
# parametry rate i ceil zależą od "gatunku" klienta
# (konkretniej od tego ile płaci)

tc class add dev $interface parent 1:20 classid 1:$klasa htb \
    rate $rate ceil $ceil prio 4

tc qdisc add dev $interface parent 1:$klasa handle $uchwyt: tbf \
    rate $ceil latency 200ms burst 1540

tc filter add dev $interface parent 1:0 protocol ip prio 12 \
    handle $numer fw classid 1:$klasa

#konfiguracja ograniczenia koozy na ssanie
#ponieważ mam tu trochę nietypowo, więc piszę "mniej więcej"
#coś podobnego - czyli może nie działać...
#CEIL zależy od ilości wyjść na świat - czyli ok. 1600 * n
#rate i ceil oczywiście dla każdego klienta różne
#muszę tu dać tbf - nie mogę pozwolić klientowi na zbytnie
#rozpędzenie się bo inny klient o niższym SNR może w ogóle
#nie wbić się w przekaźnik


tc qdisc add dev eth1 root handle 1: htb default 2
tc class add dev eth1 parent 1: classid 1:1 htb \
    rate ${CEIL}kbit ceil ${CEIL}kbit

#a to dla nie-klientów - ze względu na charakter sieci (radio)
#muszę i tu dać ograniczenia. Defaultowo wędruje tu wszystko
#co nie jest klientem

tc class add dev eth1 parent 1: classid 1:2 htb rate 2000kbit ceil 2000kbit
tc qdisc add dev eth1 parent 1:2 handle 20 sfq

#no i dla każdego klienta:

tc class add dev eth1 parent 1:1 classid 1:$klasa htb \
    rate $rate ceil $ceil prio 2

tc qdisc add dev eth1 parent 1:$klasa handle $uchwyt: tbf \
    rate $ceil latency 200ms burst 1540

tc filter add dev eth1 parent 1:0 prio 10 protocol ip u32 \
match ip dst $klient_ip classid 1:$klasa

4) I na koniec - żeby żadna menda mi się nie wbiła w sieć (jest to 
bezpieczne, bo kliencki AP podaje zawsze swojego MAC-a i zmiana 
sieciówki u klienta nie powoduje konieczności przestawiania czegokolwiek):

# dla każdego klienta:
arp -s $ip_klienta $mac_klienta

5) Dodatkowo: wszystkie przekażniki ustawione są tak, że klient może 
połączyć się wyłącznie z MAC-em bramy. Co prawda na początku wywoływało 
to wielkie pretensje klientów (bo nie mogą sobie nawzajem filmów 
przegrywać po LANie - problem ze zrozumieniem różnicy między radiem a 
ethernetem mieli jakoś wszyscy) - po pewnym czasie (i po demonstracji, 
jak dwa AP-ki z dobrym SNR-em skutecznie blokują całą transmisję) chyba 
zrozumieli bo przestali się czepiać... A przy okazji dość dobrze 
rozwiązuje to problem snifferów (owszem, podsłuchanie transmisji 
radiowej też jest możliwe, ale wymaga trochę więcej niż ściągnięcie 
sobie windzianego execa)

To tak mniej więcej tyle...

ethanak





Więcej informacji o liście dyskusyjnej pld-users-pl