Ograniczanie ruchu w połączeniu ze SQUID-em

15 lipca 2009, by: kozik

Niektórzy ludzie nie szanują współdzielonego łącza – zapuszczają P2P czy P2M i ssą bez opamiętania, więc warto mieć w zanadrzu możliwość ograniczenia ruchu dla wybranych wewnętrznych IP. Niestety router z kształtowaniem ruchu (traffic-shaping) jednocześnie jest transparentnym serwerem proxy (SQUID), który mocno komplikuje tu sprawę… ale da się to zrobić.

Rozwiązanie rozszerza mój wcześniejszy problem z wieloma interfejsami i zakłada już działający traffic shaper, coś w stylu:

# Liczenie limitow lacza (4096/512 kbit). Limity u nas musza byc troszke nizsze,
# aby to u nas odbywalo sie kolejkowanie, a nie po stronie modemu ADSL lub u providera.
FULL_UP_RATE_NUM=$(expr 512 \* 97 / 100)    # % lacza
FULL_UP_RATE="${FULL_UP_RATE_NUM}kbit"
# Ruch ograniczany, czyli hot-spot i jakis gosciu nas wkurwia:
BAD_UP_RATE_PERCENT=1
BAD_UP_RATE_NUM=$(expr ${FULL_UP_RATE_NUM} \* $BAD_UP_RATE_PERCENT / 100)
BAD_UP_RATE="${BAD_UP_RATE_NUM}kbit"
BAD_UP_CEIL="$(expr ${FULL_UP_RATE_NUM} \* 15 / 100)kbit"    # 20->250kB, 15->200kB
BAD_QUANTUM="1600"
BAD_PRIO=5
BAD_CLASS=13
# Kolejnosc filtrowania - priorytety:
MARKS_FILTER_PRIO=2
# Z konfiguracji iptables:
MARK_TRAFFIC_LAN_HOTSPOT="0x1"
# Dolaczamy do glownego wezla HTB klasy:
tc class add dev ${WAN} parent 1:1 classid 1:${BAD_CLASS} htb rate ${BAD_UP_RATE} \
ceil ${BAD_UP_CEIL} prio ${BAD_PRIO} quantum ${BAD_QUANTUM}
# Filtry, czyli przypisanie ruchu do poszczegolnych klas
# Bad traffic /how do ya like it assholes? :)
tc filter add dev ${WAN} parent 1:0 protocol ip prio $MARKS_FILTER_PRIO \
handle $MARK_TRAFFIC_LAN_HOTSPOT fw flowid 1:${BAD_CLASS}

Powyższe reguły dla tc przekierują ruch oznaczony MARK-iem $MARK_TRAFFIC_LAN_HOTSPOT do qdisca HTB (Hierarchy Token Bucket) z górnym limitem 15% łącza ($BAD_UP_CEIL) i gwarantowaną przepustowością 1% łącza ($BAD_UP_RATE_PERCENT).

Teraz wystarczą reguły iptables do oznaczania ruchu:

TRAFFIC_LOWER_PRIO_IP="192.168.1.111 ... ..."
LAN_LABO="eth2"
MARK_TRAFFIC_LAN_HOTSPOT="0x1"
# Lower priorytetu dla IP:
if [ "$TRAFFIC_LOWER_PRIO_IP" != "" ]; then
for ip in $TRAFFIC_LOWER_PRIO_IP ; do
iptables -t mangle -A PREROUTING -i $LAN_LABO -p TCP --source $ip -j MARK \
--set-mark $MARK_TRAFFIC_LAN_HOTSPOT
done
fi

Wszystko wyglądałoby pięknie – ruch od wrednego gościa jest oznaczany w firewallu i na tej podstawie traffic shaper wrzuca go do mocno przyciętej klasy. Problem wprowadza jednak SQUID dla ruchu HTTP (i ew. innego), który jako transparentny proxy ma regułę:

iptables -t nat -A PREROUTING -i ${LAN_LABO} -p TCP --dport 80 -j REDIRECT --to-port ${SQUID_PORT}

w efekcie powodującą, że oznaczony (MARK) przez nas pakiet trafia do SQUID-a, a ten tworzy i wysyła całkowicie nowy datagram w świat. Znika tym samym bezpowrotnie nasz MARK i pakiety nie mogą być przez traffic shapera prawidłowo rozpoznane. Rozwiązanie jest pokrętne – w konfiguracji SQUID-a /etc/squid/squid.conf:

# Wrzućmy wybrane "złe" IP do grupy hotspot:
acl hotspot src 192.168.1.111/32
# Reszta ludków leci do standardowej grupy labo:
acl labo src 192.168.0.0/16
# Teraz każdemu wychodzącemu pakietowi z grupy hotspot dajmy jakąś flagę TOS:
tcp_outgoing_tos 0x08 hotspot
# Żeby flagować TOS-em wybrane pakiety, trzeba wyłączyć utrzymywane połączenia:
server_persistent_connections off

A do reguł iptables dodajmy oznaczanie MARK-iem pakietów z flagą TOS:
SQUID_HOTSPOT_TOS="0x08"
iptables -t mangle -A OUTPUT -p TCP --dport 80 -m tos --tos $SQUID_HOTSPOT_TOS \
-j MARK --set-mark $MARK_TRAFFIC_LAN_HOTSPOT

i w efekcie każdy wychodzący ruch (HTTP z pośrednictwem SQUID-a jak i zwykły) dla danego IP będzie przez tc regulowany. Działa? Działa… ale wystarczy, że użytkownik nada sobie inny IP (pominie DHCP) i można cmoknąć się… :)

Wysłano w Blog - Linux i Unix | Tagi: | Brak komentarzy »

Adres dla trackback. RSS dla komentarzy w tym wpisie.
Dodaj komentarz




Uwaga: Włączona jest moderacja komentarzy, więc nowy komentarz nie ukaże się bezpośrednio po jego wysłaniu.

Uwaga: Działa filtr antyspamowy. Jeśli umieścisz w komentarzu odnośniki, to może on zostać błędnie zakwalifikowany jako spam.