@D:
Tekst pokazuje prosty sposób na monitorowanie obciążenia łącza do interentu, z podziałem na sieci docelowe lub usługi za pomocą rrd i iptables.

@T:
Monitorowanie ruchu za pomocą rrd i iptables.

@V:  
Ostatnio przez Internet przetoczyła się dyskusja spowodowana problemami z transmisją na styku sieci akademickich - Pol-34 a siecią TP S.A. Oczywiście, jak zwykle poszło o pieniądze i dodatkowo, żeby sprawę utrudnić, można było odnieść wrażenie, że poza pieniędzmi chodziło o ambicje dwóch, bardzo dużych jak na nasze polskie warunki, sieci.
@V
W trakcie tej dyskusji przerzucano się statystykami błędów, obciążeń, wielkością styków z danym operatorem, itp. Dodatkowo pojawiło się wiele głosów omawiających kierunki ruchu, w którym idzie większość ruchu internetowego od większych i mniejszych operatorów, pomiędzy jakimi sieciami wymiana ruchu jest zbliżona, gdzie jest asymetryczna itd. Ponieważ sam byłem ciekaw jak to jest naprawdę i kto tak naprawdę korzysta z danych zgromadzonych na moim serwerze, postanowiłem się temu przyjrzeć.
@V
Sytuacja była o tyle skomplikowana, że chodzi o jeden serwer z Linuksem na pokładzie, a nie o router z oprogramowaniem gotowym do generowania takich statystyk za pomocą NetFlow. Ostatecznie okazało się to prostsze niż się spodziewałem i już wiem od kogo mogę żądać peeringu;)
@V
Celem było potwierdzenie lub zaprzeczenie tezie, jakoby gros ruchu z większości sieci szło w kierunku TP S.A., przy okazji dodatkowym zadaniem było ograniczenie ruchu ftp do określonego poziomu. Całość musiała się rozstrzygnąć przy pomocy narzędzi ogólnie dostępnych w oparciu o dane zgromadzone z niedużego serwera z Linuksem, z serwerem ftp z popularną zawartością i kilkoma mniejszymi rzeczami (www, smtp, pop3).

@ZT:
Zabawa w kopciuszka czyli zliczanie pakietów.

@L:
Żeby móc zacząć robić statystyki musiałem zacząć od posortowania ruchu wg kategorii, które chciałem później analizować. Interesowały mnie tak naprawdę cztery kategorie ruchu:

- całość ruchu wychodzącego z serwera
- ruch wychodzący w kierunku TP S.A.
- ruch wychodzący w kierunku GTS, w tym wypadku głównego dostawcy łącza
- ruch wychodzący ftp generowany przez użytkownika, z którego prawami działał serwer ftp z dostępem anonimowym

@L:
Po przeczesaniu freshmeat.net i googlowaniu za odpowiednimi narzędziami ostatecznie okazało się, że poczciwe iptables jest doskonałym narzędziem do zabawy w Kopciuszka.

@L:
Wykorzystałem łańcuch mangle, który pozwalał na znakowanie pakietów wg kategorii określonych powyżej. Mangle poza możliwością znakowania ruchu jest celem nieterminującym, czyli pakiety, które zostaną wysłane do tego właśnie celu, są dalej przetwarzane przez iptables. Do samego ograniczania ruchu ftp z serwera skorzystałem z pomocy tc.

@L:
Poniżej krok po kroku przedstawiam konfigurację iptables, która pozwoliła na pogrupowanie ruchu, oznakowanie ruchu i okresowe zbieranie statystyk.

@L:  
Na początek dla porządku czyszczę cały łańcuch mangle:

@LI:
iptables -t mangle -F

@L:
Żeby móc coś powiedzieć o ilości danych przesyłanych w określonym kierunku potrzebowałem informacji o sumie ruchu wychodzącego z serwera. Aby oznakować cały ruch utworzyłem własny łańcuch i tam skierowałem wszystkie pakiety wychodzące. W łańcuchu tym pakiety wpadające do niego otrzymują znacznik 0x11.

@KT:Znakowanie wszystkich pakietów
@LI:
iptables -t mangle -X all_data
iptables -t mangle -N all_data


iptables -t mangle -A OUTPUT -o $ETH  -j all_data

iptables -t mangle -A all_data -j MARK  --set-mark 0x11

@L:
Oczywiście można to zrobić w jednym łańcuchu, ale ponieważ zliczane będą jeszcze inne grupy pakietów, zależało mi na jednakowym sposobie sumowania ruchu wychodzącego.

@L:
Podobnie znakowany będzie ruch wychodzący w kierunku operatora. Warto zwrócić uwagę, że znaczniki nadane we wcześniejszych liniach będą nadpisywane przez kolejne, jeśli pakiety trafią do różnych łańcuchów. W tym przypadku będzie tak zawsze, bo każdy pakiet wychodzący w kierunku GTS jest także pakietem wychodzącym w ogóle.

@KT:Znakowanie pakietów wychodzących w kierunku GTS
@LI:
iptables -t mangle -X gts
iptables -t mangle -N gts

iptables -t mangle -A OUTPUT -o $ETH -d 195.94.192.0/19  -j gts
iptables -t mangle -A OUTPUT -o $ETH -d 217.8.160.0/19 -j gts
iptables -t mangle -A OUTPUT -o $ETH -d 217.153.0.0/16 -j gts

iptables -t mangle -A gts -j MARK --set-mark 0x21

@L:
Pojawia się przy okazji pytanie skąd brać aktualne zakresy adresów IP przypisane do danego operatora. Te dane udostępniają serwery whois. Jeśli chcę uzyskać spis sieci przyznanych TP S.A. wystarczy użyć polecenia:

@KT:Wyszukiwanie prefiksów rozgłaszanych przez operatora
@LI:
vix:~# whois -h filtergen.level3.net RIPE::AS5617

vix:~# whois -h filtergen.level3.net RIPE::AS5617
Prefix list for policy RIPE::AS5617 = RIPE::AS5617

80.48.0.0/13
83.0.0.0/11
194.204.128.0/18
...

@L:
Podobnie jak powyżej oznaczałem pakiety skierowane do sieci GTS, oznaczam pakiety wychodzące do sieci TP S.A. Należy tylko zmienić zakresy sieci docelowych  (opcja -d) oraz znacznik, którego użyję (opcja -set-mark).

@KT:Znakowanie pakietów wychodzących w kierunku TP S.A.
@LI:
iptables -t mangle -X tpnet
iptables -t mangle -N tpnet

iptables -t mangle -A OUTPUT -o $ETH -d 80.48.0.0/13  -j tpnet
iptables -t mangle -A OUTPUT -o $ETH -d 83.0.0.0/11 -j tpnet
iptables -t mangle -A OUTPUT -o $ETH -d 194.204.128.0/18 -j tpnet
...
...

iptables -t mangle -A tpnet -j MARK --set-mark 0x31

@L:
Pozostaje mi policzyć pakiety wysyłane do użytkowników mojego serwera ftp. Tę regułkę zostawiam na koniec po to, aby żadne inne nie nadpisały znacznika w przypadku ściągania danych z serwera ftp przez użytkowników GTS. Gdyby znakowanie według adresów GTS następowało po znakowaniu ruchu ftp, nie mógłbym później ograniczać ruchu z serwera ftp, bo część znaczników zostałaby nadpisana.

@KT:Znakowanie wychodzących pakietów ftp
@LI:
iptables -t mangle -X ftp
iptables -t mangle -N ftp

iptables -t mangle -A OUTPUT -o $ETH \
-m owner --uid-owner anonftp -j ftp

iptables -t mangle -A ftp -j MARK --set-mark 0x41

@L:
Następnie sprawdzam czy ruch jest rzeczywiście zliczany:

@KT:Pokazywanie informacji o wychodzących danych ftp
@LI:
vix:~# iptables -t mangle -L ftp -n -v -x
Chain ftp (1 references)
    pkts      bytes target     prot opt in     out     source               destination
 1002842 1356515158 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           MARK set 0x41

@L:
Połowa zadania jest wykonana: pakiety zostały poznakowane i są już zliczane. Ruch ftp mogę następnie w dogodny dla siebie sposób ograniczyć za pomocą tc.

@KT:Ograniczenie ruchu wychodzącego ftp
@LI:
tc qdisc del dev $ETH root
tc qdisc add dev $ETH root handle 1: htb default 10

tc class add dev $ETH parent 1: classid 1:1 htb rate 2mbit ceil 2mbit

tc class add dev $ETH parent 1:1 classid 1:10 htb rate 2mbit prio 1
tc class add dev $ETH parent 1:1 classid 1:20 htb rate 1024kbit prio 2

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

tc filter add dev $ETH protocol ip parent 1: prio 2 handle 0x41 \
 fw flowid 1:20

@ZT:
Wykresy.

@L:
Teraz przydałoby się pokazać zebrane dane w jakiejś rozsądnej postaci. Zdecydowałem się na rrd, które jest następcą zasłużonego i wysłużonego mrtg. rrd daje znacznie większe możliwości jeśli chodzi o manipulację danymi gromadzonymi w bazach .rrd jak i o prezentację wyników w formie wykresów.

@L:
Na początku trzeba stworzyć plik .rrd, w którym będą zbierane informacje:

@KT:Tworzenie pliku w którym będa zbierane statystyki RRD
@LI:
rrdtool create stats.rrd -s 60           \
        DS:all_data:COUNTER:600:0:U      \
        DS:gts:COUNTER:600:0:U           \
        DS:tpnet:COUNTER:600:0:U         \
        DS:ftp:COUNTER:600:0:U           \
        RRA:AVERAGE:0.5:1:10080          \
        RRA:AVERAGE:0.5:2:5040           \
        RRA:AVERAGE:0.5:4:2520           \
        RRA:AVERAGE:0.5:6:1680           \
        RRA:AVERAGE:0.5:180:56           \
        RRA:AVERAGE:0.5:360:28


@L:
Polecenie to tworzy plik stats.rrd inicjując kolejno cztery źródła danych - DS. Każde ze źródeł będzie przechowywać informacje o określonym typie ruchu. Minimalna wartość została ustalona na 0, maksymalna jest niezdefiniowana U. Dane będą pobierane co 60 sekund, a  przechowywane próbki określane są przez rekordy RRA.

@LI:
RRA:AVERAGE:0.5:1:10080

@L:
Średnia z jednej próbki, czyli z 60 sekund; przechowywanych będzie 10080 próbek, co daje ostatecznie:

 10080 min / 60 minut / 24 godziny = 7 dni.

@LI:
RRA:AVERAGE:0.5:180:56

@L:
Średnia ze 180 próbek, czyli z trzech godzin; przechowywanych będzie 56 próbek. Ostatecznie daje to:

 3 godziny * 56 próbek =  174 godziny = 7 dni.

@L:
Po szczegółowy opis parametrów rrd odsyłam do stron rrd, może warto tylko dodać, że jako typ danych został wybrany COUNTER, ponieważ pozwala on zliczać stale rosnące dane i dobrze radzi sobie z przewijającymi się licznikami.

@L:
Następnie będę wypełniać plik stats.rrd danymi sczytywanywanymi w odstępach jednominutowych. Do tego wykorzystam prosty skrypcik uruchamiany poprzez cron w następujący sposób:

@LI:
* * * * * /home/mazek/bin/update.sh

@L:
Sam skrypt ma za zadanie odczytać stan liczników dla podanych łańcuchów oraz wprowadzić te dane do bazy rrd.

@KT:Skrypt do aktualizowania danych w pliku rrd
@LI:
#!/bin/bash

ITM="/sbin/iptables -t mangle"

# Pobieramy liczbę bajtów z podanego łańcucha.
ALL_DATA=`$ITM -L all_data -n -x -v | tail -n 1 | awk -F " " {'print $2;'}`

GTS=`$ITM -L gts -n -x -v | tail -n 1 | awk -F " " {'print $2; '}`

TPNET=`$ITM -L tpnet -n -x -v | tail -n 1 | awk -F " " {'print $2; '}`

FTP=`$ITM -L ftp -n -x -v | tail -n 1 | awk -F " " {'print $2; '}`

# Wprowadzamy dane pobrane do pliku .rrd
rrdtool update stats.rrd N:$ALL_DATA:$GTS:$TPNET:$FTP


@L:
I tu zaczyna się najlepsze, czyli narysowanie tego co zgromadziłem. rrd daje pod tym względem ogromne możliwości w porównaniu do swojego porzednika - mrtg. Możliwości prezentacji danych przez rrd w różnoraki sposób są naprawdę imponujące i dla kogoś, kto wcześniej korzystał z mrtg -  wręcz przytłaczające;)

@L:
Na początek zgromadzę wszystkie dane na jednym wykresie:

@KT:Generowanie wykresu
@LI:
COMMENT="Ostatnia aktualizacja: "` date +"%d/%m/%Y %T"`

rrdtool graph stats1.gif --title="Ruch wychodzący z vix" \
         -w 700  --start -129600 \
          DEF:all_data=stats.rrd:all_data:AVERAGE \
          DEF:gts= stats.rrd:gts:AVERAGE \
          DEF:tpnet= stats.rrd:tpnet:AVERAGE \
          DEF:ftp= stats.rrd:ftp:AVERAGE \
          DEF:www= stats.rrd:www:AVERAGE \
          HRULE:100000#000000:"MAX limit" \
          LINE3:all_data#0000ff:"Cały ruch z vix"\
          LINE2:gts#ff0000:"Ruch do GTS"\
          LINE2:tpnet#fff000:"Ruch do TPNET"\
          LINE2:ftp#00ffff:"Ruch ftp z serwera"\
          LINE2:www#888282:"Ruch www z serwera"\
          COMMENT:"                                           "\
          COMMENT:"$COMMENT" \
          --vertical-label "bits/sek"

@L:
To polecenie wykonuję za każdym razem, kiedy chcę obejrzeć najnowsze dane z pliku stats.rrd. Można je także wrzucić do crona i wykonywać w wybranych okresach czasu. Wykres wygenerowany za pomocą tego polecenia będzie prezentował dane z ostatnich trzydziesty sześciu godzin (129600 sekund). Parametr DEF określa źródło danych i sposób ich interpretowania. Mnie interesuje wartość średnia z przedziału czasowego, czyli AVERAGE. Ponieważ chcę pokazać całość na jednym wykresie, definiuję cztery źródła danych. Linię wykreślającą całość ruchu z serwera rysuję najgrubszą linią - LINE3, kolorem czerwonym - wartość rgb: ff0000, pozostałe będą kreślone linią średniej grubości - LINE2 w różnych kolorach. Na dole wygenerowanego obrazka dodana zostanie legenda łącząca kolory z określonym typem ruchu pokazywanego, oraz komentarz.

@Bi:mark41.gif
@B:Rysunek 1: Wykres pokazujący wszystkie typy zliczanego ruchu.

@L:
Rysunek 1 pokazuje wszystkie typy ruchu monitorowanego na jednym wykresie. Każdy z rodzaj ruchu pokazywany jest za pomocą linii. Uzyteczność tego typu wykresów jest więc ograniczona.

@L:
Żeby nie mieszać rzeczy niepowiązanych ze sobą, czyli statystyk typu ruchu (ftp, www) i celu danych (TP S.A., GTS), rozbijam poprzedni wykres na dwa oraz próbuję sprawić żeby stał się bardziej czytelny.

@KT:Generowanie wykresu
@LI:
rrdtool graph stats2.gif --title="Ruch z eth vix, z podzialem na sieci" \
          -w 700  --start -129600  \
          DEF:all_data= stats.rrd:all_data:AVERAGE \
          DEF:gts= stats.rrd:gts:AVERAGE \
          DEF:tpnet= stats.rrd:tpnet:AVERAGE \
          AREA:all_data#0000ff:"Cały ruch z vix"\
          AREA:tpnet#fff000:"Ruch do TPNET"\
          STACK:gts#ff0000:"Ruch do GTS"\
          --vertical-label "bits/sek"

@Bi:mark42.gif
@B:Rysunek 2: Ruch pogrupowany wg celu danych.

@L:
Rysunek 2 pokazuje zestakowane dane o ruchu wychodzącym wg. celu pakietów wychodzących.  

@KT:Generowanie wykresu
@LI:
rrdtool graph stats3.gif --title="Ruch z eth vix, z podzialem na usługi" \
          -w 700  --start -129600 \
          DEF:all_data= stats.rrd:all_data:AVERAGE \
          DEF:ftp= stats.rrd:ftp:AVERAGE \
          DEF:www= stats.rrd:www:AVERAGE \
          AREA:all_data#0000ff:"Cały ruch z vix"\
          AREA:ftp#00ffff:"Ruch FTP"\
          STACK:www#888282:"Ruch WWW"\
          --vertical-label "bits/sek"

@Bi:mark43.gif
@B:Rysunek 3: Ruch pogrupowany wg typu danych.

@L:
Rysunek 3 pokazuje zestakowane dane o ruchu wychodzącym wg. usług. W tym przypadku badamy jedynie ftp  i www.

@L:
W obydwu przypadkach utworzone zostały wykresy pokazujące dane z ostatnich sześciu godzin. Źródła danych (DEF) zostały ograniczone tylko do tych, które mnie interesują. Co najważniejsze, zmienił się także sposób prezentacji. Zamiast linii wykreślających poziom ruchu danego typu, pokazuję wypełnione obszary. W obydwu przypadkach całość ruchu jest pokazywana kolorem granatowym. Na Rys. 2. na obszarze granatowym pokazywane są dane o ruchu do sieci GTS i TP S.A. Ruch do sieci TP S.A. pokazany jest za pomocą koloru żółtego, do sieci GTS za pomocą koloru czerwonego. Jak widać, można spokojnie rozpoczynać negocjacje z TP S.A. w kwestii darmowej wymiany ruchu;)
    
@L:
Co ważne, ruch do różnych sieci pokazywany jest w formie zestakowanych a nie nakładających się obrazów dzięki użyciu słowa kluczowego STACK. Podobnie jest na rysunku 3., który pokazuje różne typy ruchu. Granatowy kolor oznacza całość ruchu wychodzącego, jasnoniebieski obszar to wychodzący ruch ftp a szary obszar to ruch www.

@L:
Jak widać, za pomocą prostych i powszechnie dostępnych narzędzi można uzyskać bardzo ciekawe informacje. Oczywiście rozwiązania te nie zastąpią zintegrowanych narzędzi do analizy ruchu, ale w dużym stopniu mogą ułatwić zarządzanie siecią i dostępnym pasmem.

@IT:Info
@IL:
[1] Strona domowa projektu RRD
<U>http://www.rrdtool.com/<U>
@IL:
[2] Strona domowa projektu NetFilter
<U>http://www.netfilter.org/<U>

@IT:Autor
@IL: Marcin Mazurek ...