logo
PolskiPL Flag EnglishUK Flag Strona NiceShapera
[14.12.2005]
Uwaga do ostatnio dodanych filtrów wkradł się bład, oczywiście handle dla filtrów nie mogą być identyczne.
Wklejenie do systemu drugiego filtra skutkowało komunikatem:
"RTNETLINK answers: File exists".
Poprawione.
[07.12.2005]
Dodałem opis przygotowania katalogów oraz dysku dla squida.
Uaktualniłem też przedstawione filtry HTB tak by traktowały zarówno transparentne proxy jak i świadomie uzywane przez klientów.


Squid i patch ZPH TOS


Jak wiemy Squid jest popularnym serwerem proxy, poprawnie skonfigurowany może znacząco przyśpieszyć ładowanie stron www. jako że wiele rozbudowanych serwisów jest do granic możliwości wypełniona drobnymi plikami .gif, jpg, czy .swf. których wczytanie nawet gdy dysponujemy szybkim łączem może się rozciągnąć w czasie. Co wynika z faktu że na każdy plik oczekujemy przynajmniej kilkadziesiąt milisekund. By uzmysłowić sobie problem wystarczy ten czas pomnożyć przez liczbę potrzebnych plików. Serwer proxy zapamiętuje te pliki w tzw. cache czyli pamięci operacyjnej i dyskowej, serwując nam je lokalnie przy każdym następnym odwołaniu dzięki czemu szybkość wyświetlania się stron zależna jest juz wyłącznie od prędkości renderowania silnika przeglądarki na maszynie klienckiej. Niestety w podstawowej konfiguracji gdzie mamy do czynienia z dzieleniem łącza, czy to przy użyciu czystego HTB czy programu typu NiceShaper, możliwości te nie do końca są wykorzystane, gdyż pliki trafione i chybione lądują najczęściej w jednej kolejce, implikując fakt że pakiety HItowe nie obciążają nam łącza internetowego, można dojść do wniosku że trzeba nam je rozróżnić od pakietów MISSowych ( HIT - pliki serwowane z cache, MISS - pliki pobrane z internetu ).

Zagadnienie to często sprawia wiele problemów a istnieje proste rozwiązanie polegające na znakowaniu pola TOS pakietów, wymagające jedynie prostego patcha na squida, a że sam proces kompilacji squida nie jest skomplikowany zdecydowałem się go tutaj opisać krok po kroku.


Tak więc zaczynamy.
Na początek potrzebne nam będą źródła squida z http://www.squid-cache.org oraz ZPH TOS patch z http://www.it-academy.bg/zph/
W chwili pisania artykułu najnowszą stabilna wersja squida to 2.5STABLE12 i na niej oprę dalszy opis.
Bezpośredni link do źródeł: http://www.squid-cache.org/Versions/v2/2.5/squid-2.5.STABLE12.tar.gz
zważając na fakt że wersje stabilne nie wprowadzają rewolucyjnych zmian można założyć że opis będzie nam służył także przy kolejnych wydaniach.
Orginalny patch z racji tego że w ostatniej wersji przeznaczony jest dla squida 2.5stable10, pociągnie za sobą przymus manualnego dokończenia patchowania
bezpośredni link do patcha: http://www.it-academy.bg/zph/squid-2.5.STABLE10-ToS_Hit.patch
jednak dla ułatwienia wygenerowałem patcha dla wersji 2.5STABLE12
patch: http://niceshaper.jedwabny.net/files/squid-2.5.STABLE12-ToS_Hit_MJ.patch

pliki sciagamy np. do katalogu /usr/src, rozpakowujemy i patchujemy:

# cd /usr/src
# gunzip squid-2.5.STABLE12.tar.gz
# tar xf squid-2.5.STABLE12.tar
# cd squid-2.5.STABLE12
# cat ../squid-2.5.STABLE12-ToS_Hit_MJ.patch | patch -p1

naszym oczom powinny okazać się komunikaty w tym guście:
patching file src/cf.data.pre
patching file src/client_side.c
patching file src/structs.h

Po czym przechodzimy do kompilacji.
Oto wywołanie skryptu configure z przykładowym zestawem opcji:

# ./configure --prefix=/squid \
--with-dl \
--with-aio \
--with-pthreads \
--enable-underscores \
--enable-large-files \
--enable-linux-netfilter \
--enable-removal-policies=heap,lru \
--enable-storeio=ufs,aufs,diskd \
--enable-http-violations \
--enable-cache-digests \
--enable-err-language=Polish \
--enable-delay-pools

dalej już kompilacja i instalacja:

# make
# make install

po czym w katalogu /squid powinniśmy otrzymać binaria oraz pliki składające się na kompletny pakiet squida

# cd /squid
edytujemy config znajdujący się w pliku /squid/etc/squid.conf
i samodzielnie konfigurujemy squida zwracając uwage na opcje:

zph_tos_local 8
zph_tos_peer 0
zph_tos_parent off

ew. podmieniamy na poniższy przykładowy config: http://niceshaper.jedwabny.net/files/squid.conf

Przed uruchomieniem squida należy jeszcze udostępnić mu przestrzeń dyskową na cache. jak można zauważyć w udostępnionym configu, montujemy ją w punkcie /var/spool/squid, co ważne squidowi powinniśmy udostępnić dysk na wyłączność, niema mowy o tym by cache squida znajdowało się na dysku systemowym!!!
Co więcej jeśli mamy tylko te dwa dyski, dysk dla squida montujemy jako secondary na osobnej taśmie.
Tak więc na całej przestrzeni dysku tworzymy jedną partycję, montujemy ją z opcjami: noatime,nodiratime,noexec.
Reasumując w pliku /etc/fstab powinna się znaleść taka linijka:

/dev/hdc1 /var/spool/squid xfs defaults,noatime,nodiratime,noexec 0 0

Słowem wyjaśnienia na serwerach proxy używam xfs jako systemu plików, może i faktycznie ext2 lub reiserfs byłby kilka procent szybszy, lecz zdania na ten temat są tak podzielone że póki sam nie przeprowadze konkretnych testów używam tego z czego jestem zadowolony.

wykonujemy:

# mkdir /var/spool/squid
# mount -a
# chown proxy:proxy /var/spool/squid
# chmod 755 /var/spool/squid
# mkdir /var/log/squid
# chown proxy:proxy /var/log/squid
# chmod 755 /var/log /squid
# ln -s /squid/sbin/squid /usr/sbin/squid
# squid -z

Uruchamiamy naszego squida:

# squid -D -YC

# ps axf

powinno nam wykazać squida w uruchomionych procesach. Jeśli tak jest możemy sprawdzić czy zapytania są poprawnie obsługiwane:

# links www.google.com -http-proxy 192.168.1.1:8080

gdzie 192.168.1.1 to adres ip na którym proxy nasłuchuje zapytań od klientów.

Transparentne proxy:

Teraz zadajemy sobie krótkie pytanie: Czy nasze proxy ma być transparentne?
Odpowiadamy TAK!!
I wprowadzamy do firewalla odpowiednią rególke przekierowującą zapytania klientów na lokalnie nasłuchującego squida:

iptables -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.1.0/24 --dport 80 -j DNAT --to-destination 192.168.1.1:8080

Teraz gdy nasze proxy wreszcie pracuje, mogę wreszcie opisać jak sprawić by pakiety z cache squida nie były cięte przec HTB/NS.
Jako że dzięki patchowi powinniśmy uzyskać możliwość łatwego rozpoznania czy pakiet jest HITowy czy MISSowy,
działanie squida po włączeniu możemy sprawdzić za pomocą tcpdumpa:

# tcpdump -nv -i eth1 src port 80

Gdzie eth1 to interfejs LAN ( dla wygody także w dalszej części będę posługiwał się interfejsem ETH1 mając na myśli interfejs LAN ). Pola TOS jak można zauważyć mają wartości 0x0 lub 0x8, 0x8 to pakiety trafione i póki cache nie zostanie w pewnym stopniu zapełnione pewnie jest ich stosunkowo niewiele. 0x0 to oczywiście pakiety chybione.

Siłą rzeczy doszliśmy do gwoździa programu, musimy zdecydować jak potraktujemy nasze pakiety z cache. Sensownym i prostym rozwiązaniem wydaje się być utworzenie jednej wspólnej kolejki, dla całości ruchu HItowego bez separowania klientów od siebie, zważywszy na periodyczny charakter ruchu www nie powinno nam to sprawiać problemów. Dla przykładu użyłem tu widełek o wielkości 4mbit. Należy zadbać by poniższe linie zostawały automatycznie odpalone zawsze po restarcie NiceShapera, co jest wygodne a nawet wskazane:

# tc class add dev eth1 parent 1:1 classid 1:8 htb rate 4096kbit ceil 4096kbit
# tc qdisc add dev eth1 parent 1:8 handle 8: sfq perturb 10
# tc filter add dev eth1 protocol ip parent 1:0 prio 10 handle 800::8 u32 match ip protocol 0x6 0xff match ip sport 80 0xffff match ip tos 0x8 0xff flowid 1:8
# tc filter add dev eth1 protocol ip parent 1:0 prio 10 handle 800::9 u32 match ip protocol 0x6 0xff match ip sport 8080 0xffff match ip tos 0x8 0xff flowid 1:8

iptablesą serwujemy poniższą regółkę by zapobiec zliczaniu tego ruchu przez NS:
iptables -t mangle -I POSTROUTING -o eth1 -p tcp --sport 8080 -m tos --tos 8 -j ACCEPT

UWAGA: IMQ!!

przy method mark lub none sprawa wygląda w miarę prosto, jako że IMQ ( przynajmniej u siebie obserwuje takie zjawisko ), w ogóle "nie widzi" ruchu ze squida, nawet tego MISSowego, nie zalecam stosowania method IMQ na routerach ze squidem. Jak się uprzeć można IMQ pogodzić ze squidem lecz port 80 traktujemy dalej na interfejsach fizycznych nie na samym IMQx. Co ważne PRZED!! dodanie powyższej kolejki do HTB należy utworzyć kolejke root na interfejsie lanowym, w końcu w method imq interfejsy fizyczne są czyste jeśli chodzi o HTB.:

# tc qdisc del root dev eth1
# jednak dla pewności czyścimy interfejs # tc qdisc add dev eth1 root handle 1: htb default 1
# tc class add dev eth1 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit

dodajemy też kolejkę dla ruchu MISSowego, nad nim tym bardziej chcemy uzyskać kontrolę:

# tc class add dev eth1 parent 1:1 classid 1:10 htb rate 2048kbit ceil 2048kbit
# tc qdisc add dev eth1 parent 1:10 handle 10: sfq perturb 10
# tc filter add dev eth1 protocol ip parent 1:0 prio 10 handle 800::6 u32 match ip protocol 0x6 0xff match ip sport 80 0xffff match ip tos 0x0 0xff flowid 1:10
# tc filter add dev eth1 protocol ip parent 1:0 prio 10 handle 800::7 u32 match ip protocol 0x6 0xff match ip sport 8080 0xffff match ip tos 0x0 0xff flowid 1:10

z uwagi że nie ma idealnej metody na pogodzenie squida z imq powyższy akapit zostawiam zaawansowanym administratorom, do rozbudowy według własnego uznania.

UWAGA: TRANSPARENTNE PROXY i iptables!!

Jest jeszcze rzecz na którą muszę zwrócić uwagę, w sytuacji gdy squida mamy na porcie 8080 i jest on transparenty, przez iptables ruch ze squida do klientów widziany jest jako pochodzący z portu 8080 a przez tc już jako pochodzący z portu 80.


Powyższa konfiguracja została przetesowana i sprawnie pracuje na maszynach AMD Athlon64 z systemem Linux Debian Sarge AMD64, oraz na tradycyjnych Athlonach z dystrybucją Debian Sarge i386.


Mariusz Jedwabny, Zabrze 2005
http://www.jedwabny.net