České vysoké učení technické v Praze Fakulta elektrotechnická
Diplomová práce
Vizualizace geografických informací o síťovém provozu Bc. Pavel Bucek
Vedoucí práce: Dr. Sven Ubik
Studijní program: Elektrotechnika a informatika strukturovaný magisterský Obor: Informatika a výpočetní technika květen 2008
ii
Prohlášení Prohlašuji, že jsem svou diplomovou práci vypracoval samostatně a použil jsem pouze podklady uvedené v přiloženém seznamu. Nemám závažný důvod proti užití tohoto školního díla ve smyslu §60 Zákona č. 121/2000 Sb., o právu autorském, o právech souvisejících s právem autorským a o změně některých zákonů (autorský zákon).
V Mladé Boleslavi dne 21. 5. 2008
.............................................................
iii
iv
Abstract Network traffic analysis is still actual subject. Data transmission efficiency demands are increasing and therefore is need to know how improve existing network. This work describes network characteristics processing and generating graphs depending on geographical locality. Generated statistics can be used to internet connection optimization eventually to choose optimal location for new servers.
Abstrakt Sledování síťového provozu je stále aktuálnější téma. Požadavky na propustnost sítí stále rostou a proto je nutné vědět, jaké linky je potřeba posílit. Tato práce se zabývá zpracováním a zobrazením charakteristik o síťovém provozu v závislosti na geografické poloze. Vygenerované statistiky mohou být použity k optimalizaci internetové konektivity, popřípadě ke zvolení optimálního umístění nových serverů.
v
vi
Obsah Seznam obrázků
ix
Seznam tabulek
xi
1 Úvod 1.1 Historie Internetu . . . . . . 1.2 Protokoly . . . . . . . . . . 1.2.1 NCP . . . . . . . . . 1.2.2 TCP/IP . . . . . . . 1.3 Adresování . . . . . . . . . . 1.4 DNS - Domain name service 1.5 Autonomní systémy . . . . . 1.6 Směrování . . . . . . . . . . 1.6.1 BGP . . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
1 1 4 4 5 7 8 9 10 10
2 Popis problému a analýza řešení 2.1 Geografická lokalizace IP adres 2.2 Netflow . . . . . . . . . . . . . 2.3 IPFIX . . . . . . . . . . . . . . 2.4 Zachytávání datagramů . . . . . 2.5 Výkon a škálování aplikace . . . 2.6 Datové struktury . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
12 12 12 15 16 16 17
3 Architektura systému 3.1 dump2sql . . . . . . . . . 3.2 Databáze . . . . . . . . . 3.3 Zobrazování charakteristik 3.4 Skripty pro sběr dat . . . 3.5 Další implementační části 3.5.1 nfdump . . . . . . 3.5.2 samplicator . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
18 19 22 23 23 24 24 24
4 Implementace 4.1 dump2sql . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Zobrazování charakteristik a agregace dat . . . . . . . . . . . . . . . . .
25 25 29
5 Testování 5.1 Výsledky měření . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33 34
6 Závěr
36
7 Literatura
37
A Seznam použitých zkratek
39
B Definice typů použitelných v NetFlow verze 9
43
. . . . . . .
. . . . . . .
. . . . . . .
vii
C Obsah přiloženého média
49
viii
Seznam obrázků 1.1 1.2 1.3 1.4 1.5 1.6 1.7
Arpanet 1969, převzato z [2] . . . . . . . . . . . . . . . . . . Arpanet 1973, převzato z [3] . . . . . . . . . . . . . . . . . . Počet stanic v internetu, převzato z [7] . . . . . . . . . . . . TCP IP, převzato z [7] . . . . . . . . . . . . . . . . . . . . . Logo organizace ICANN . . . . . . . . . . . . . . . . . . . . Struktura DNS databáze, převzato z [7] . . . . . . . . . . . . Border Gateway Protokol – konečný automat, převzato z [7]
. . . . . . .
2 3 5 6 7 8 11
3.1 3.2 3.3
Architektura systému . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Škálování . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Použití programu nprobe . . . . . . . . . . . . . . . . . . . . . . . . . . .
18 19 19
4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8
Závislosti souboru parseconf.c . . . . . . . . . . . . Závislosti souboru support.cpp . . . . . . . . . . . . Vývojový diagram programu dump2sql . . . . . . . Call graph programu dump2sql . . . . . . . . . . . Ukázka typu zobrazení charakteristik – bar . . . . . Ukázka typu zobrazení charakteristik – circle . . . . Ukázka typu zobrazení charakteristik – mapEurope Ukázka typu zobrazení charakteristik – mapUSA . .
. . . . . . . .
26 26 28 29 30 31 32 32
5.1
KCacheGrind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
ix
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . .
. . . . . . . .
. . . . . . .
. . . . . . . .
. . . . . . .
. . . . . . . .
. . . . . . .
. . . . . . . .
. . . . . . .
. . . . . . . .
. . . . . . .
. . . . . . . .
x
Seznam tabulek 5.1
Měření propustnosti datagramů . . . . . . . . . . . . . . . . . . . . . . .
xi
35
xii
KAPITOLA 1. ÚVOD
1
1 Úvod Tato práce se zabývá zachytáváním záznamů o uskutečněných datových přenosech v internetu, které jsou generovány a exportovány buď směrovači, nebo pomocí speciálního software. Jejím cílem je zpracování takto zachycených informací a vygenerováním charakteristik v závislosti na geografické poloze. V následujících odstavcích shrnu základní informace o internetu, adresování a směrování v této síti, dále se budu věnovat analýze mého problému, návrhu řešení i samotné implementaci. Nakonec uvedu změřenou propustnost celého implementovaného systému a budu se snažit zhodnotit přínos této práce a použitelnost vzniklého produktu.
1.1
Historie Internetu
Jako velké množství technologií a přenosových sítí, má i internet své kořeny v armádě. V této kapitole se popíšu vznik této unikátní celosvětové sítě a dát ho do souvislosti s jinými důležitými událostmi. Základ Internetu byl položen v Americe, ve Spojených státech. Počátky vzniku bychom mohli vysledovat už v roce 1950, kdy byla založena NSF – National Science Foundation, která měla podporovat rozvoj výuku, vědy a vývoje matematiky, fyziky, medicíny a různých dalších vědních oborů. Tehdejší zaměstnanci pracovali pro NSF většinou na poloviční úvazek a paralelně pracovali pro americké unverzity. V roce 1951 byla na MIT založena Linkolnova laboratoř, která se měla zabývat obranou proti střelám s dlouhým doletem. Další důležitá událost se stala v roce 1957 – rusové vypustili první umělý satelit lidstva – Sputnik. Ukázali tím světu, že jsou schopni mimo jiné vytvořit mezikontinentální střelu. Toto zcela jistě odstartovalo vědecký boj mezi Ruskem a Spojenými státy. Tehdejší prezident Eisenhower (generál z druhé světové války) si byl vědom důležitostí tohoto počinu a dělal vše pro to, aby USA udržely s Ruskem krok. Stanovil prezidentského poradce pro vědu a výzkum (první byl jmenován prezident MIT James R. Killian Jr.). V roce 1958 byla jako reakce na ruský úspěch založena ARPA – Advanced Research Project Agency. Agentura byla stvořena v rámci amerického ministerstva obrany a měla se zabývat vytvořením vlastních raket. Brzy bylo ale rozhodnuto, že tento výzkum by měl probíhat v civilní agentuře, takže založili další – NASA (National Aeronautics and Space Administration). Po tomto kroku se ARPA zaměřila na výzkum informačních technologií a hlavně počítačových sítí. Během roku 1960 probíhal intenzivní výzkum týkající se paketových přepínaných sítí, v Americe se jím zabývali na několika pracovištích. Byla také založena další agentura DISA (Defence Communications Agency). V roce 1961 byla do projektu ARPA zahrnuta i Computer science – počítačová věda.
2
KAPITOLA 1. ÚVOD
Byla také publikována jedna z prvních prací, zabývajících se komunikačními sítěmi: Information Flow in Large Communication Nets [Leonard Kleinrock, 1961]. Tento rok je také dalším milníkem v historii lidstva. Rusové vypustili Vostok 1, na jehož palubě byl Yuri Gagarin, první člověk ve vesmíru. Američané prohráli další bitvu, ale nevzdávali se. Tři týdny potom vyslali vlastní raketu s Alanem Shepardem na palubě a testovali ji v sub-orbitálních letech. Další krok bylo založení univerzitních mainframů – obrovských počítačů, které byly ale oddělené, nemohli spolupracovat. Myšlenka jejich propojení je logickým vyústěním této situace, protože její realizací by se daly sdílet prostředky mezi univerzitami, což by vedlo k značné úspoře finančních prostředků.
Obrázek 1.1: Arpanet 1969, převzato z [2]
V roce 1963 ARPA poprvé představila myšlenku celosvětové sítě. Návrh se jmenoval Intergalactic Computer Network (ISOC). Americká vláda projekt čile podporovala a výsledek na sebe nenechal dlouho čekat. V roce 1965 byla poprvé demonstrována geograficky rozsáhlá počítačová síť. V roce 1967, v rámci ARPANet Design Session bylo navrhnuto použití minipočítačů, které by se staraly o tok paketů v síti, místo toho, aby se o přepínání staraly mainframy samy. Byla tedy navržena jakási servisní podsíť. Projekt se vyvíjel celkem rychlým tempem, ale ne všichni z něj měli radost. Univerzity, které se ho účastnily, najednou neměly moc velkou motivaci sdílet své prostředky, měli své vlastní mainframy a takhle by vlastně jenom přicházely o výpočetní čas vlastních strojů (financovaných z prostředků ARPA). ARPA je ale právě díky tomu donutila na ARPANetu spolupracovat, respektive podmínila tím svou další podporu. V rámci tohoto procesu byla definována první přenosová rychlost 2400 bps a specifikována ASCII abeceda. V tomto období se také objevuje publikace, ve které bylo prvně použito slovo „paketÿ. Vývoj pokračoval, v roce 1969 je vyvinut IMP - Interface Message Processor, který se
KAPITOLA 1. ÚVOD
3
měl stát „hloupýmÿ směrovačem, organizující provoz na síti. Nic už tedy nebránilo tomu, dát několik takových procesorů dohromady a vytvořit první paketovou síť v historii lidstva. Ten okamžik byl zrodem ARPANetu, čtyři jednotky propojeny 50 kbps pronajatými okruhy. Stalo se tomu na podzim roku 1969. Spojily se tři univerzity – University of California (UCLA a UCSB), Stanford University a Utah University. Byl proveden experiment s přenosem prvních dat, poprvé se člověk vzdáleně přihlásil k jinému počítači a operoval s daty vzdálené databáze. Stala se ještě jedna důležitá věc – byl publikován první RFC dokument – RFC 0001 [6], týkající se softwarového vybavení účastníků sítě (IMP). Jen pro zajímavost zde také uvedu, že první návrh počítal s propojením maximálně 64 zařízení. Dokumenty RFC jsou jak je vidno s Internet jako takovým těsně spjaty. Je zajímavé, že i když dokumenty netvoří žádnou závaznou normu, jsou obecně dodržovány a software i hardware většinou přesně splňuje postupy v nich popsané, nebo alespoň podmožinu, pokud by byla celá implementace příliš náročná. RFC dokumenty nejsou vytvářeny nějakou autoritou, většinou je to tak, že nějaký expert nebo tým expertů navrhne řešení existujícího problému, vytvoří vzorovou implementaci, otestují funkčnost a potom se vytvoří „Internet draftÿ. Pokud je toto řešení uznáno za přínosné, stane se z něj oficiální RFC se svým neměnným číslem. Po prvním uskutečněném datovém přenosu se síť už rozšiřovala velmi rychle. Lidé si brzy uvědomili, co za věc se vlastně podařilo udělat a k čemu všemu se dá využít. Už v roce 1970 ARPANet spojoval východní a západní pobřeží Spojených států, o rok později tato síť spojovala už devatenáct počítačů. V tom roce byl také poprvé poslán po „internetuÿ Email (zajímavé je, že úplně první Email byl odeslán a přijat už v roce 1965, tehdy se ale doručoval pouze v rámci jednoho stroje). Tato služba se stala nejvyužívanější službou v tehdejší síti. V roce 1972 Ray Tomlinson vymyslel první mailovou infrastrukturu a adoptoval zavináč @ jako oddělovač uživatelského jména a jména stroje v adrese.
Obrázek 1.2: Arpanet 1973, převzato z [3] V roce 1975 byla prezentována síť SATNET, která propojovala Spojené státy, Anglii a
4
KAPITOLA 1. ÚVOD
Norsko. Také vznikla první komerční společnost nabízející přepínané sítě. V roce 1976 si email poslala také anglická královna a ARPANet se stal dominující světovou sítí. Postupně se k němu připojovaly další a další sítě. Vznik OSI se datuje rokem 1977, v ten samý rok bylo také demonstrováno propojení různých sítí (ARPANet, SATNET, PRNET, . . .) pomocí IP protokolu (ARPANet běžel stále na protokolu NCP – Network Control Program). Opět pro zajímavost – tehdejší IP protokol byl navržen pro propojení maximálně 256 sítí, tehdy se to zdálo jako dlouhodobě dostačující počet. V roce 1978 se protokol IP (tehdy IPv3) rozdělil na TCP a IP, čímž později usnadnil vznik UDP. V roce 1978 vznikla první BBS (Bulletin Board System) – CBBS zprovozněná Wardem Christensenem, umožňovala lidem sdílet software. BBS byly počítače připojené k telefonní síti modemem. Uživateli nestačilo jen znát telefonní číslo, potřeboval i jméno a heslo, kterým se autorizoval. V rámci jednoho systému mohli uživatelé sdílet data a vyměňovat si zprávy – emaily. Postupem času se BBS připojily k Internetu a víceméně zanikly. Vrstvový model OSI vznikl v roce 1979, ve stejném roce vznikla i dodnes existující síť USENet, poskytující prostředí pro komunikaci. Vznikla také organizace Configuration Control Board (předchůdce Internet Engineering Task Force). Síť se začala používat i pro zábavu, vznikl první MUD – Multi User Dungeon. Byl to program, nejlépe definovatelný asi jako textová hra, ve kterém se ale mohlo potkat více uživatelů a prožívat spolu různá dobrodružství. Je to předchůdce dnešních MMORPG (Massively Multiplayer Online Role-Playing Game), jako třeba Ultima Online nebo World of Warcraft. Do ARPANetu se připojovalo stále více uživatelů a vznikaly speciální terminály, jako například Minitel. Byla pro něj dostupná mimo jiné hra – šachy, ve které byl implementovaný chat, který se stal brzy používanější než hra samotná. ARPANet se formálně stal Internetem v roce 1983, kdy celý přemigroval z protokolu NCP na IP. Podrobnější informace naleznete v [3], [2] a [7].
1.2 1.2.1
Protokoly NCP
Protokol NCP (Network Control Program) je první protokol navržen pro komunikaci pomocí paketů. Implementuje protocol stack na stroji připojeném do ARPANetu. NCP poskytuje správu konekcí a proudů mezi účastníky sítě. Služby jako doručování emailů nebo přenos souborů byly postaveny právě na NCP. ARPANet fungoval zhruba tak, že fyzická, linková a síťová vrstva se používala pro komunikaci mezi různými IMP. Komunikace mezi počítačem a IMP byla specifikována v HOST/IMP protokolu.
KAPITOLA 1. ÚVOD
5
Obrázek 1.3: Počet stanic v internetu, převzato z [7]
NCP byla vlastně vyšší vrstva – transportní, která se skládala z AHHP (ARPANet Host to Host Protocol) a ICP (Initial Connection Protocol). Už z názvů protokolů lze usoudit, k čemu se používaly. AHHP definoval postupy k vytvoření jednosměrného toku dat mezi dvěma účastníky sítě a ICP definoval postup vytváření dvou takových spojení, aby bylo možno komunikovat obousměrně. Aplikační protokoly potom už jen využívaly definované rozhraní.
1.2.2
TCP/IP
Prvního ledna roku 1983 byl protokol NCP prohlášen za zastaralý a jeho roli převzala rodina protokolů TCP/IP. Na začátku se sluší zmínit, že protokoly označované souhrnně jako TCP/IP se dodnes používají a stále se vyvíjí, ať už nové, nebo různé varianty stávajících. Z nových bych vybral například SCTP, potenciální náhradu TCP protokolu, z modifikací lze vybrat například úpravy TCP pro speciální bezdrátové sítě. Standard definuje podobně jako NCP jednotlivé vrstvy. Konkrétně jsou 4: aplikační, transportní, síťová a linková. Každá z vrstev má přesně definované rozhraní a každá vrstva přijímá příkazy od sousední vyšší a přikazuje sousední nižší. Není tedy možné, aby protokol z aplikační vrstvy přímo využíval nějaký z linkové. Linková vrstva zodpovídá za přenos dat mezi dvěma sousedními účastníky. Typické protokoly pro ni jsou PPP, HDLC, Ethernet a podobné. Adresování na této úrovni může být různé, v nejpoužívanější síti dneška, Ethernetu, se na této úrovni adresuje pomocí MAC adres, které jsou v zařízeních většinou pevně nastaveny už od výroby. Ze síťových prvků na této vrstvě pracují typicky switche (přepínače). Síťová vrstva se stará o směrování a přenos datagramů. Také přiřazuje každému účast-
6
KAPITOLA 1. ÚVOD
níku sítě jedinečnou IP adresu. Typické protokoly pro tuto vrstvu jsou IP, ICMP, ARP a RARP. Aktuálně se používá verze IPv4, ale ve světě jsou i iniciativy vedoucí k přechodu na IPv6. Děje se tomu tak proto, že světu pomalu ale jistě začíná docházet rozsah adres, které IPv4 poskytuje. IPv4 definuje adresy ve tvaru čtyř osmibitových čísel, tj. dohromady může být jednoznačně identifikováno v síti 232 počítačů. Na světě jich existuje s největší pravděpodobností mnohem víc, ale na Internetu se začaly používat určitá schémata, která počet efektivně používaných IP adres snižují (například NAT – Network Address Translation: překlad síťových adres).
Obrázek 1.4: TCP IP, převzato z [7]
Transportní vrstvu reprezentují už přímo protokoly pro výměnu dat, momentálně nejpoužívanější jsou TCP a UDP. TCP poskytuje spolehlivou bezchybnou komunikaci, zajišťuje doručení všech zpráv v pořadí, ve kterém jsme je poslali. Mezi dvěma účastníky umožňuje vytvořit obousměrný tok dat. UDP poskytuje pouze posílání jednotlivých datagramů, kde není zaručeno jeji pořadí při doručení a ani to, že dorazí ke svému adresátovi. Transportní vrstva definuje také svoje adresování – specifikuje, že každé zařízení připojené do sítě má 65536 portů, které mohou být nezávisle používány. Smysl to má například když chce více aplikací komunikovat najednou nebo když stanice poskytuje více služeb. Každé spojení má nějaké lokální číslo portu (nemusí být schodné se vzdáleným), podle kterého se bezproblémově identifikuje. Aplikační vrstva je reprezentována bohatou skupinou protokolů, patří sem například protokoly pro výměnu emailů (SMTP, POP, IMAP, . .), pro přenos souborů (FTP), pro překlad adres na jejich textové ekvivalenty (DNS) a například i DHCP, kterým se zařízení může zeptat nějakého serveru na svou IP adresu. Právě transportní a aplikační vrstva nás budou v této práci zajímat nejvíce. Obě dvě se totiž dají využít k určení geografické polohy účastníka internetu, což je jedním z cílů této práce.
KAPITOLA 1. ÚVOD
1.3
7
Adresování
Přidělování adres v Internetu, respektive ARPANetu má také svou historii. Na začátku byl počet účastníků tak malý, že nebylo potřeba tento problém nějak složitě řešit, ale s postupem času, jak se ARPANet rozšiřoval, bylo potřeba do adresování zanést nějaký řád (už jen kvůli tomu, aby se nestalo, že si dva účastníci přivlastní stejnou adresu). První pokus o nějaký centrální registr byl zaznamenán v RFC 322, který byl publikován 26. března, 1972. Jméno IANA (Internet Assigned Numbers Authority) bylo poprvé zmíněno až v RFC 1060, ale už v něm se dá vysledovat vazba na předchozí. IANA byla původně založena americkou vládou po hlavičkou ARPY a ISI (Information Sciences Institute). V roce 1998 byla v Kalifornii založena nezisková organizace ICANN (Internet Corporation for Assigned Names and Numbers), která převzala veškeré aktivity organizace IANA. ICANN spadá pod americké ministerstvo obchodu (Department of Commerce). Dnešní ICANN se dělí na několik organizačních celků, nás však zde bude zajímat nejvíce pouze asi ASO (Address Suporting Organisation) a CCNSO (Country Code Names Supporting Organization). ASO má na starost přidělování IP adres v rámci internetu. Není to ale tak, že by celosvětově fungovala pouze jedna organizace. ASO pouze rozděluje rozsahy adres jednotlivým RIR (Regional Internet Register), které mají delegovanou pravomoc o přerozdělování adres v rámci svého regionu. Budu se jim ještě věnovat v další části této práce. CCNSO má na starost přidělování národních domén nejvyšší úrovně. Teoreticky by tedy stačilo pouze zjistit jmenný záznam dané IP adresy a věděli bychom, ve které zemi se daný stroj nachází. Mimo národních domén existují ale i generické (.com, .net, . . .), které si mohou lidé zaregistrovat kdekoli na světě. Více o jmenných záznamech si můžete přečíst v kapitole DNS.
Obrázek 1.5: Logo organizace ICANN Regionálních Internetových registrů je několik, konkrétně jsou to ARIN (American Registry for Internet Numbers), RIPE NCC (RIPE Network Coordination Centre), APNIC (Asia-Pacific Network Information Centre), LACNIC (Latin American and Caribbean Internet Address Registry) a AfriNIC (African Network Information Centre). Dohromady tvoří NRO (Number Resource Organization) a starají se o přidělování adres celému světu. Hlavní úkol NRO je „chránitÿ nerozdělený adresní prostor (před neefektivním přidělením). Na počátku existence podobných organizací se totiž adresní rozsahy přidělovaly „kde komuÿ, protože adres bylo dost. Tehdy si lidé nepřipouštěli, že by mohly jednou
8
KAPITOLA 1. ÚVOD
dojít. Vznikly tak společnosti, které mají přiděleno až šestnáct milionů adres (například Hewlett Packard, Ford, IBM a další), které s největší pravděpodobností nedokážou využít (čti: vystačili by si s mnohem menším rozsahem).
1.4
DNS - Domain name service
Domain name service se do češtiny překládá jako doménová jmenná služba. Zajišťuje na Internetu překlad jmen na IP adresy a vyhledání reverzního záznamu (překlad IP adresy na jméno). Celý tento systém je realizován DNS servery, které jsou rozmístěny po celém Internetu. Díky jim například můžeme do webového prohlížeče napsat www.google.com místo 66.249.91.99. Jak to celé funguje? Princip je relativně jednoduchý. Pokud chcete přeložit nějaké jméno na IP adresu, pošlete požadavek na DNS server. Mimo jiné z toho plyne, že je potřeba znalost IP adresy DNS serveru – kdyby bylo známo pouze jeho jméno, nebylo by možné ho přeložit. Ten potom odpoví. Odpovědí může být buď přímo IP adresa, nebo informace, že se server o danou doménu nestará a že není ochotný hledaný záznam najít. Abych byl přesný, existují i dva druhy dotazů: rekurzivní a nerekurzivní. Rekurzivní dotaz je právě takový, kdy je po DNS serveru požadováno, aby hledal dále za tazatele (pokud danou doménu neobhospodařuje přímo on), nerekurzivní dotaz očekává buď přímou odpověď nebo alespoň radu, kde se ptát dál, tj. DNS server pouze odkáže tazatele na nějaký další server.
Obrázek 1.6: Struktura DNS databáze, převzato z [7]
Celý takto navržený systém se neobejde bez centrálního řízení. Znamená to, že musí někde existovat takzvané root servery, které mají informace o tom, kde se nacházejí servery pro dané TLD (Top Level Domain). Například pokud bychom chtěli znát IP adresu záznamu google.com a náš DNS server by odmítal rekurzivní dotaz, byla by první odpověď právě IP adresa jednoho z root serverů. Jeho odpověď na stejný dotaz by byla asi taková: „neznám google.com, ale vím, kdo má na starost TLD .comÿ. Takto bychom se postupně dostali až k DNS serveru, který google.com zná. Jediný rozdíl mezi rekurzivním a nerekurzivním voláním je tedy ten, že pří nerekurzivním aktivně oslovuje DNS servery přímo uživatel a při rekurzivním to za něj dělá jeho DNS server.
KAPITOLA 1. ÚVOD
9
Jak bych celý systém DNS serverů mohl použít pro hledání geografické polohy? Pokud by mi stačilo rozlišit pouze státy, mohl bych si ke každé zaznamenané IP adrese najít odpovídající TLD a podle ní adresu klasifikovat. Bohužel ale existují již dříve zmíněné generické domény, o kterých bych takto nezjistil nic. Také ne všechny státy mají jasně definované, kdo může vlastnit doménu registrovanou pod jejich TLD – lépe definováno – většina jich neřeší státní příslušnost a nechá doménu zaregistrovat komukoli. Omezení na občana státu také nic moc neřeší, protože potom stačí registrátorovi založit v takové zemi pobočku a vše registrovat přes ní. Prohledávání DNS záznamů je také značně pomalé a nevyhovovalo by požadavkům vyvíjeného systému.
1.5
Autonomní systémy
Autonomní systémy (AS) na Internetu úzce souvisejí se směrováním (routováním). V rámci lokální sítě mohou nastat dvě varianty - buď počítač leží v dané síti a lze s ním komunikovat přímo, nebo neleží a datagram se musí poslat nějakému stroji, který se nachází na stejné lokální síti a bude zodpovídat za předání paketů do další sítě. Takovému zařízení se říká router, česky směrovač. Když se nad tímto schématem zamyslíte, určitě vás napadne, že by bylo celkem těžké mít například záložní linku do Internetu zařízenou tak, aby se v případě výpadku hlavní linky kdokoli dostal do vaší sítě bez toho, aby byl výpadkem nějak omezen. Toto se dá řešit až pokročilými routovacími protokoly, které fungují právě mezi jednotlivými autonomními systémy. Na druhou stranu, když se podíváme na Internet z globálního pohledu, první od sebe rozeznatelné sítě budou právě jednotlivé autonomní systémy. Po detailnějším průzkumu jejich struktury bychom objevili, že existují tři základní druhy. „Mutlihomed ASÿ je takový systém, který je propojený s nejméně dvěma dalšími. Takový AS je nezávislý na jedné lince, dokáže si elegantně poradit s výpadkem jakékoli linky, bez toho, aby omezil uživatele, kteří jsou jeho součástí. Multihomed AS však nedovoluje jiný přenos dat, než od sebe a k sobě. Není tedy možné přes něj připojit další AS. „Stub ASÿ je systém, který se zdá být připojený pouze jednou linkou k jinému. Nabízí se otázka, proč by vznikal a proč není součásti toho, ke kterému je připojený. Odpověď je jednoduchá – může být spojený s dalšími autonomními systémy, ale jejich propojení není veřejné. Typicky to mohou být různá propojení bankovních organizací nebo jiná B2B (Business-to-business) spojení. „Transit ASÿ jsou takové, které oproti Multihomed AS dovolují přenos dat skrz vlastní síť. Typicky jsou to AS poskytovatelů internetového připojení, ty jsou v této kategorii vždy. Nejlepší definice je asi „AS, které poskytuje přenos dat z jedné sítě do druhéÿ. Směrování mezi jednotlivými AS je realizováno pomocí BGP (Border Gateway Protocol), který se budu snažit popsat v následující kapitole Směrování.
10
1.6
KAPITOLA 1. ÚVOD
Směrování
Směrování je obecně postup zjištění cesty datagramu k jeho cíli. Je hodně závislé na typu sítě a existuje několik druhů směrování. Nejjednodušší rozdělení je asi na statické a dynamické. Statické směrování je takové, kdy pro každého účastníka sítě existuje jakási tabulka, která pokrývá všechny možné destinace datagramů. Z té se pouze vybere a datagram je odeslán určeným směrem. Tabulka je v tomto případě nastavena staticky, například od lokálního administrátora. Takové směrování je pro nás nezajímavé a hlavně je nepoužitelné v síti, v které se účastníci různě přesouvají (například mobilní sítě). Dynamické směrování je statickému podobné, rozdíl je jen v tom, kdo naplní směrovací tabulky. Zde to bude nějaký algoritmus. Základní rozdělení je zde na takzvané distancevektor a link-state algoritmy. Typickými zástupci těchto typů algoritmů jsou RIP (Routing Information Protocol) a OSPF (Open Shortest Path First). O těchto protokolech a o směrování obecně by se dala napsat nejméně celá tato práce, zaměřím se zde tedy pouze na to, co má souvislost s cílem mého snažení. RIP i OSPF se používá pouze v rámci jednoho autonomního systému. Pro použití mezi autonomními systémy by byly neefektivní a například RIP by ani pro své omezení nešel ve stávající podobě nasadit. Pro směrování mezi AS bylo postupem času vymyšleno několik protokolů, aktuálně se používá BGP (Border Gateway Protocol) ve verzi 4, která se v současném Internetu začala používat v roce 1994 a všechny předchozí verze byly prohlášeny za zastaralé.
1.6.1
BGP
BGP je nejdůležitější směrovací protokol internetu. Jak už jsem naznačil dříve, směruje provoz mezi jednotlivými autonomními systémy. K tomu používá routovací tabulku, ve které je vždy adresa sítě (s maskou) a informace, ke kterému AS se má provoz směrovat. BGP nepoužívá klasické jednoduché metriky, pří rozhodování kudy se datagram pošle rozhoduje několik atributů, jako například vypočtená cesta k cíli, pravidla vázaná k síti a vlastní (lokální) nastavení. BGP může být provozován i v rámci nějakého AS, potom se označuje jako IBGP (Internal BGP). IBGP je vhodné používat v sítích, které se často mění, respektive ve kterých je běžné, že se například nějaký přístupný bod připojuje k různým směrovačům (multihoming). Kdybychom tento protokol porovnávali například s RIPem, první, čeho si všimneme bude asi množství informací posílaných při nějaké změně. V případě RIPu se přenáší celá směrovací tabulka, BPG přenáší pouze změnu (protože celá routovací tabulka je z pravidla příliš velká a výměna všech dat by zahltila celou síť). Směrovač podporující BPG se dá popsat jako konečný automat obsahující šest stavů: Idle, Connect, Active, OpenSent, OpenConfirm, a Established. Pro každé spojení s dalším směrovačem si směrovač vytvoří proměnnou, ve které má uložen momentální stav. BPG protokol přesně specifikuje zprávy, které si mohou oba účastníci vyměňovat v závislosti na
KAPITOLA 1. ÚVOD
11
Obrázek 1.7: Border Gateway Protokol – konečný automat, převzato z [7]
aktuálním stavu. V prvním stavu, „Idleÿ, protokol inicializuje všechny prostředky a zatím odmítá všechny pokusy o komunikaci od ostatních směrovačů ale sám začne s ostatními spojení navazovat. Druhý stav, „Connectÿ, reprezentuje navazování spojení. Směrovač v něm zůstane dokud se nezkompletuje TCP spojení a poté se změní na „OpenSentÿ. Pokud se spojení nepodaří navázat, stane se aktivním stav „Activeÿ, nastaví se čítač ConnectRetry a po jeho vypršení se vrací do stavu „Connectÿ. Pokud se spojení naváže, jsme tedy ve stavu „OpenSentÿ. V něm si směrovače vymění zprávy KeepAlive a pokud je přenos úspěšný, je spojení na obou stranách přepnuto do stavu „Establishedÿ a směrovač může vysílat nebo přijímat zprávy KeepAlive, Update a Notification. Kdybyste chtěli někde BGP nasadit, potřebujete buď nějaký směrovač s podporou BGP, nebo pokud chcete ušetřit, existují i open source implementace, jak například GNU Zebra pro linux nebo OpenBGPD pro OpenBSD.
12
KAPITOLA 2. POPIS PROBLÉMU A ANALÝZA ŘEŠENÍ
2 Popis problému a analýza řešení V této kapitole se budu snažit co nejpřesněji popsat řešený problém a zdůvodňovat použitá řešení.
2.1
Geografická lokalizace IP adres
Geografická lokalizace podle IP adresy jen pomocí veřejně dostupných služeb je problém. Nabízí se pouze systém DNS, ale hledání reverzního záznamu ke každé adrese je časově náročné (pomalá odezva DNS serverů), navíc získaná informace je velmi diskutabilní (není problém zaregistrovat si v česku například ruskou doménu a zajistit si nastavení i takového reverzního záznamu). Další možný způsob lokalizace je přes databázi regionálních internetových registrátorů. Databáze obsahuje rozsahy jednotlivých IP adres a z uvedených údajů se dá zjistit země a často i město a přímo adresa „majiteleÿ rozsahu. Problém u takto uvedených údajů je jejich přesnost, například u mezinárodních společností může dojít k rozprostření přiděleného rozsahu do více zemí. Větší problém je, podobně jako při hledání reverzních DNS záznamů, s rychlostí odezvy a zde dokonce i s omezeným počtem dotazů za časový interval. Sdružení CESNET, z. s. p. o. mi dalo k dispozici zakoupenou databázi od společnosti MaxMind, která tuto službu umožňuje. Existují dokonce přímo volně dostupná rozhraní pro několik programovacích jazyků a zároveň i volně šiřitelná verze databáze (ve které je garantovaná nižší přesnost a neposkytuje další údaje jako například město a zeměpisnou šířku a délku). Po několika zběžných testech se ukázalo, že databáze od společnosti MaxMind je použitelná a perfektně se hodí k našemu účelu. Jediný problém s tímto produktem je, že zatím podporuje pouze IPv4 adresy. Pro úplnost – společnost MaxMind není jediná, která nabízí podobný produkt. Existují produkty například od společností IP2LOCATION (http://www.ip2location.com/) nebo QUOVA (http://www.quova.com/) nabízejí stejnou funkcionalitu a podobnou garantovanou přesnost jako produkt koupený CESNETem.
2.2
Netflow
Netflow je otevřený ale proprietární protokol pro přenos informací o síťovém provozu. Byl vyvinut společnosti Cisco. Aktuální (a s nejvetší pravděpodobností i poslední) verze je 9 (RFC 3954, viz [6] a [1]), nejpoužívanější je nejspíš stále verze 5 (jsou aplikace, kde není potřeba upgrade na verzi 9). Verze 9 se od verze 5 liší hlavně v tom, že umožňuje definovat šablonu jednotlivých flow s více sledovanými charakteristikami než verze 5,
KAPITOLA 2. POPIS PROBLÉMU A ANALÝZA ŘEŠENÍ
13
čímž dovoluje získávat více informací o datovém toku. Mnou implementovaný program umí zpracovávat pouze Netflow verze 9, protože je to jediná použitelná verze, která umožňuje přidávat vlastní typy dat do šablon. V budoucnu se totiž předpokládá, že bude program sloužit mimo jiné právě k zpracování těchto nově přidaných typů. Netflow záznamy jsou posílány typicky v UDP datagramech a asi jako v každém protokolu, v datagramu je přítomna nejdříve hlavička a pak samotná data. Data mohou obsahovat definice šablon (nemusí být jen jedna) a nakonec vlastní flow. Detailněji strukturu hlavičky protokolu Netflow zobrazuje následující obrázek (převzato z [1]): 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version Number | Count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | sysUpTime | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | UNIX Secs | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Potom následují buď definice šablon, nebo přímo data. To rozlišujeme podle první další položky – FlowsetID. Pokud je roven nule, jedná se o definice šablon, pokud je větší než nula, jde o data. Souvisí s tím i rozdílné formátování údajů, které by mělo být pochopitelné z následujících obrázků.
14
KAPITOLA 2. POPIS PROBLÉMU A ANALÝZA ŘEŠENÍ 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | FlowSet ID = 0 | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Template ID 256 | Field Count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Field Type 1 | Field Length 1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Field Type 2 | Field Length 2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ... | ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Field Type N | Field Length N | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Template ID 257 | Field Count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Field Type 1 | Field Length 1 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Field Type 2 | Field Length 2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ... | ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Field Type M | Field Length M | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ... | ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Template ID K | Field Count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ... | ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Jak je vidět, definuje ID šablony (TemplateID), její délku, typy hodnot, které obsahuje a jejich délky. Všechny možné typy hodnot jsou uvedeny v příloze B. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | FlowSet ID = Template ID | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Record 1 - Field Value 1 | Record 1 - Field Value 2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Record 1 - Field Value 3 | ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Record 2 - Field Value 1 | Record 2 - Field Value 2 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Record 2 - Field Value 3 | ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Record 3 - Field Value 1 | ... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ... | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
KAPITOLA 2. POPIS PROBLÉMU A ANALÝZA ŘEŠENÍ
15
Záznam obsahující pouze data je ve velmi jednoduchém formátu. Skládá se přímo ze syrových dat, nijak neoddělených. Jistě to je kvůli efektivnímu využití datagramů s Netflow záznamy, ovšem je jasné, že bez šablony se z těchto dat nedá vyčíst vůbec nic. Existuje ještě jedna možná varianta – speciální záznam s nastavením. V mé práci ho ale nevyužívám, proto ho zde nebudu uvádět. Podrobnosti o něm se dozvíte například v RFC 3954 [6].
2.3
IPFIX
IPFIX (IP Flow Information eXport protocol) je nástupcem Netflow v9. Vznikl jako úplně otevřený formát, s větší podporou nových typů dat použitelných v šabloně. Současnou (zatím jedinou) verzi definuje RFC 3917. Stejně jako Netflow slouží k přenosu informací o jednotlivých spojeních. Pro přenos vlastních dat může používat SCTP, TCP nebo UDP. Jediný větší rozdíl ve struktuře paketu (u Netflow hovoří RFC o datagramech, u IPFIX o paketech) je v hlavičce. IPFIX ji má kratší, vynechává údaj o počtu sekund od startu systému a mění význam některých ostatních (například počet záznamů v Netflow verze 9 versus délka celého paketu v IPFIX).
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version Number | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Export Time | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Observation Domain ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Další rozdíly jsou pouze v určení významu FlowsetID. Zatímco Netflow používá 0 pro šablony, IPFIX používá 2. Podobně Netflow 1 pro nastavení, IPFIX 3. Datové FlowsetID zůstává stejně jako u Netflow větší než 255. Ostatní formátování je identické, až na ten detail, že IPFIX má větší podmnožinu možných typů dat. Jsou však chytře zvoleny tak, aby existující byly kompatibilní s Netflow. Kdybychom chtěli nějak shrnout všechny informace o tomto formátu, stačilo by nejspíš napsat, že IPFIX formát definuje pouze jinou hlavičku a rozšiřuje množství typů dat umístitelných v šabloně exportovaných flow záznamů. Podrobnější informace o struktuře paketů najdete také v [4].
16
2.4
KAPITOLA 2. POPIS PROBLÉMU A ANALÝZA ŘEŠENÍ
Zachytávání datagramů
Při implementaci zachytávání samotných datagramů jsem původně uvažoval pouze s takovými, které jsou určeny přímo pro stroj, na kterém je zachytávám. S tím nebyl ze začátku problém a implementoval jsem je pomocí standardních funkcí deklarovaných v hlavičkovém souboru socket.h. Pro zachytávání UDP datagramů jsem tedy použil funkce socket, bind, select a recvfrom. Toto řešení bylo funkční do té doby, než přišel požadavek na zachytávání datagramů, které byly generovány pro jiný Netflow kolektor a měly tedy cílovou IP adresu odlišnou od IP adresy počítače, na kterém je bylo třeba zachytávat. Zachytávání takových datagramů se provádí v takzvaném promiskuitním módu. Znamená to, že musím zachytávat i datagramy, které nejsou směrovány na stroj, na kterém se ho snažím zachytávat (nemají cílovou MAC adresu schodnou s MAC adresou síťového rozhraní přítomného na daném stroji). Tato skutečnost program tvorbu programu trochu zkomplikovala, protože zachytávání takových datagramů není úplně triviální záležitost, navíc jsou potřeba zvýšená oprávnění. Pro řešení tohoto úkolu jsem zvolil knihovnu libpcap, která je přímo navržená pro podobné situace. Zachytávání datagramů s využitím open source knihovny libpcap je realizováno pomocí volání funkce pcap open live a následně pro každý datagram pcap next.
2.5
Výkon a škálování aplikace
Systém by měl zvládnout zpracovat co největší množství Netflow záznamů a nejlépe být škálovatelný ve smyslu objemu možných zpracovaných záznamů za jednotku času. Znamená to mimo jiné pokusit se o co nejefektivnější implementaci všech použitých postupů. Sběr dat ze směrovačů, přes které je realizován velký počet datových spojení, může být relativně náročný. Už jen generování záznamů je pro směrovač velkou zátěží. Problém může nastat ale i při samotném zachytávání. Představme si, že směrovač dokáže vygenerovat 5000 datagramů za minutu a nějaký program je musí nejlépe všechny zachytit a zpracovat. Samotné zachycení problém není, obtížnější je zpracování dat, obzvlášť určení geografické polohy. Když si problém rozebereme, skládá se zhruba z pěti částí. Zachycení datagramu, jeho zpracování (získání měřených hodnot), uložení hodnot do nějaké datové struktury, jejich agregace a export. Když jsem přemýšlel o možné paralelizaci, nabídla se mi asi nejjednodušší a zároveň velmi efektivní volba. Pokud budu schopný rozdělit jednotlivé datagramy obecně na n různých podmnožin a pustit n instancí programu, který jsem v tomto odstavci obecně popsal, dosáhnu teoreticky lineární závislosti zpracovaných datagramů za jednotku času na n. Výše uvedeným způsobem budu teoreticky schopen zajistit neomezenou škálovatelnost,
KAPITOLA 2. POPIS PROBLÉMU A ANALÝZA ŘEŠENÍ
17
jediné by ji mohlo ohrozit, je nedostatek procesorů. Potom by ale stačilo přeposílat datagramy na další počítače. Pokud bych přistoupil na toto řešení, musím zároveň vymyslet systém zpracování dat z jednotlivých stanic a jejich následnou agregaci.
2.6
Datové struktury
Struktura příchozích záznamů je jasně daná specifikací Netflow verze 9 a IPFIX protokolu. První problém je, jak tato data uchovat do doby, než budou agregována a exportována. Navrhl jsem docela složitou strukturu, jejíž použití se mi ale vyplatí při první agregaci a následném exportu. Každý flow záznam bude instance jedné struktury. Tyto struktury se uloží do jednoho vektoru, který bude reprezentovat všechny záznamy se stejným časovým razítkem. Další stupeň bude potom určená geografická lokace. Při vkládání se bude postupovat samozřejmě z druhé strany, tj. odshora. Nejdříve se najde odpovídající kód země, potom odpovídající časová značka. Tím se vybere vektor se všemi podobnými záznamy a přidá se do něj aktuální struktura. Tím se vyřeší jedno datové úložiště. Dále je potřeba specifikovat jak se budou data ukládat mimo program, tj. do jaké reprezentace budou exportována. Zatím uvažujme obecný model, kdy ještě nevíme, jak budou uložena na centrálním serveru. Dejme tomu, že data budou exportována do textové reprezentace tak, aby se dala na centrálním serveru co nejjednodušeji importovat. Například přímo řádek po řádku spustit nebo celý soubor použít jako vstup nějakého programu. Další (a poslední) stupeň je uložení do nějakého centrálního úložiště, které bude data skladovat už natrvalo (a bude je popřípadě umět agregovat). Na začátku se počítalo s rrd databází, kvůli její jednoduché údržbě a automatické agregaci dat. Ovšem má problém s uložením hodnot, které mají zůstat v čase konstantní. Tedy. . ne problém, jen je prostě nepodporuje, pouze počítá průměry. Znamená to, že nelze uložit přenesené bajty, musí se interpretovat jako průměrná rychlost. Bohužel to ale není jediná vada na kráse, respektive nesoulad s požadovanou funkčností. Pokud do rrd databáze přidáte záznam, automaticky se nastaví aktuální čas na „teďÿ a agregují se starší data podle definovaného vztahu. Problém je, když chcete ukládat do jedné databáze data z více zdrojů (musejí se před přidáním sečíst) a také nelze přidat data zpětně. Díky těmto faktům jsme se s vedoucím projektu dohodli, že je pro naše účely vhodnější MySQL databáze s tím, že se bude muset vytvořit navíc agregační skript.
18
KAPITOLA 3. ARCHITEKTURA SYSTÉMU
3 Architektura systému Od zadavatele nebylo přímo specifikované, v jakém programovacím jazyce by se měla daná úloha naimplementovat, ale bylo dáno prostředí, ve kterém bude muset fungovat. Program by měl být přeložitelný a spustitelný obecně na jakémkoli linuxovém / unixovém systému. S tím souvisí i přítomnost nějakého skriptovacího jazyka (konkrétně bash). Pro vizualizaci by měl sloužit web server apache s nainstalovaným mod php s knihovnou gd. Zadavatel výslovně požaduje zobrazitelnost map bez flashe, javy a javascriptu pro bezproblémový přístup z různých prohlížečů.
Obrázek 3.1: Architektura systému Na obrázku 3.1 můžete vidět základní schéma celého navrženého systému. Směrovač s podporou exportu Netflow nebo IPFIX záznamů předává informace programu dump2sql, ten je agreguje a exportuje do textových souborů. Tyto soubory jsou posléze zpracovány skripty pro agregaci a data z nich jsou uložena v MySQL databázi, se kterou komunikuje skript pro generování grafů. Z obrázku je také vidět, kde bude úzké hrdlo celého systému – v bloku označeném jako dump2sql. Právě tato komponenta bude zpracovávat největší objem dat a je potřeba se věnovat jejímu možnému škálování. Vzhledem k povaze funkce programu – zpracování příchozích datagramů – byla zvolena varianta rozdělení datového toku do několika a spuštění více instancí programu dump2sql. Tento požadavek splňuje schéma 3.2, kde je použit program samplicator, který rozděluje příchozí proud datagramů do několika menších s možností nastavení jaký podíl příchozího objemu dat se nastaví jakému odchozímu proudu. Ve uvedených schématech je ještě jedno slabé místo – směrovač, který generuje flow záznamy. Tato funkcionalita bývá většinou podporována pouze jako generování záznamů o neměnné struktuře, takže pokud by bylo třeba do Netflow záznamů ukládat nějakou další hodnotu, není toto řešení vhodné. O generování Netflow/IPFIX záznamů se ale nemusí starat jen nějaký směrovač, existují i programy, které dokáží sledovat data na lince a z nich derivují tok Netflow záznamů. Jeden z nich je nprobe, vyvíjený Lucou Derim. Tento program zadavatel už dříve používal, takže jsme vyzkoušeli i systém postavený na něm (obrázek 3.3). Hlavní výhoda je v tom, že jsou dostupné zdrojové kódy a pokud
KAPITOLA 3. ARCHITEKTURA SYSTÉMU
19
Obrázek 3.2: Škálování
by vznikla potřeba generovat statistiku, která není standardně směrovači podporována, lze ji přidat do programu nprobe. Problém ale je, že při nasazení na spoje s průtokem řádově gigabity za sekundu už program nprobe nestíhá zpracovávat všechen provoz (i na systémech s velkou výpočetní kapacitou).
Obrázek 3.3: Použití programu nprobe
3.1
dump2sql
Program dump2sql slouží k zaznamenání Netflow paketů a jejich agregaci, doplnění o geografické síťové charakteristiky a uložení do textového souboru. Vzhledem k uvažované databázi (MySQL) byly zvoleny přímo SQL příkazy, aby složitost zpracování byla co nejmenší. Program samotný jsem se rozhodl napsat v C++, protože s ním mám v podobném prostředí nejlepší zkušenosti a nabízí standardní knihovnu šablon, která mi zjednoduší implementaci datových struktur. V úvahu nepřipadal žádný interpretovaný jazyk (Java,
20
KAPITOLA 3. ARCHITEKTURA SYSTÉMU
C#), protože by to mělo negativní dopady na výkon celé aplikace. Program by měl být schopný běžet jako normální aplikace i jako systémová služba (daemon), takže vylučujeme možné ovlivňování programu ze standardního vstupu – konfigurace možná pouze vstupními parametry, popřípadě konfiguračním souborem. Specifikujme si vstupy a výstupy. Vstupy • flow záznamy (uvádím zde jen pro pořádek) • informace, kde jsou k dispozici datagramy s flow záznamy (adresa a port nebo rozhraní) • interval, po kterém se budou exportovat agregované flow s geografickými síťovými charakteristikami • informace nutné pro vytvoření SQL dotazu (jméno tabulky) • místo, kam se mají exportované soubory ukládat • filtry specifikující jméno tabulky na základě kritérií jednotlivých flow záznamů • loglevel (udává, jaké informace budou zobrazeny nebo poslány do syslogu) • běh jako normální program nebo jako služba Výstupy • soubory s SQL dotazy (každý reprezentující určitý časový interval) Datové struktury v dump2sql V předchozím testu jsem již zmínil potřebu několika datových struktur. Jako první zde uvedu strukturu reprezentující jeden flow záznam. struct traffic { unsigned long Bytes_in; unsigned long Bytes_out; unsigned unsigned unsigned unsigned
long long long long
flow_duration_in; flow_duration_out; flow_count_in; flow_count_out;
unsigned int port_src; unsigned int port_dst;
KAPITOLA 3. ARCHITEKTURA SYSTÉMU unsigned unsigned unsigned unsigned
int int int int
21
snmp_input; snmp_output; as_src; as_dst;
unsigned int direction; std::string next_hop_ipv4; }; Prvních šest atributů se agreguje a ukládá do databáze, všechny ostatní slouží pouze k možnému vyfiltrování záznamů. S filtrováním slouží další struktura, která reprezentuje jedno filtrovací pravidlo . (Všechna jsou potom reprezentována vektorem, který obsahuje jednotlivé struktury filter). Agregace dat probíhá poprvé při exportu dat, poté už podle požadavků uživatele pomocí agregačního skriptu. V podstatě se jedná pouze o prosté sčítání dat, protože všechny hodnoty, které jsou zaznamenávány, jsou vyjádřením hodnot jednoduchých veličin. Jednoduchou veličinou zde myslím například počet přenesených bytů, „složenáÿ veličina by byla například propustnost v bytech za sekundu. V případě rychlosti by se musel dělat vážený průměr v závislosti na časovém intervalu, který hodnota pokrývá. struct filter { int input_snmp; int output_snmp; string output_table; }; Je vidět, že momentálně je implementováno filtrování pouze na základě vstupního a výstupního portu routeru, který flow záznamy exportuje. Prozatím nebylo potřeba dělit záznamy podle ostatních parametrů, ale kdyby vznikla poptávka, nebylo by časově náročné tuto funkčnost naimplementovat. Nejrozsáhlejší struktura pro ukládání dat je ta, do které se ukládají všechny informace k exportu. Deklarována je následovně: map<string, map<string, vector
> > trafficMap; Když si deklaraci začneme číst odzadu, dostaneme něco jako vektor struktur traffic v asociativním poli adresovaném řetězcem a celý tento celek ještě v dalším asociativním poli adresovaném taktéž řetězcem. První řetězec reprezentuje čas a druhý zemi. Znamená to, že když chci do této struktury přidat flow záznam, musím znát dvě informace: zemi a čas. Potom postupně vyhledám odpovídající záznamy a začlením je do odpovídajícího vektoru.
22
KAPITOLA 3. ARCHITEKTURA SYSTÉMU
Další důležitá struktura je seznam všech zaznamenaných šablon.
map > > templates;
Struktura je podobná jako u struktury trafficMap, až na hodnoty, kterými jsou jednotlivá asociativní pole adresována. Obojí jsou typu int. Na nejvyšší vrstvě reprezentuje identifikační číslo exportujícího systému, na nižší je to identifikační číslo šablony. Vektor složený ze struktur template field obsahuje už samotné typy polí a jejich délku.
3.2
Databáze
Jako konečné skladiště dat byla použita MySQL databáze, mimo jiné kvůli jednoduchému přístupu k uloženým informacím. Struktura tabulky je následující:
CREATE TABLE ‘geoflow‘ ( ‘id‘ int NOT NULL AUTO_INCREMENT, ‘ts‘ int(11) default NULL, ‘duration‘ int(11) default NULL, ‘location‘ char(6) default NULL, ‘B_in‘ bigint(20) default NULL, ‘B_out‘ bigint(20) default NULL, ‘flow_count_in‘ int(11) default NULL, ‘flow_count_out‘ int(11) default NULL, ‘flow_duration_in‘ bigint(20) default NULL, ‘flow_duration_out‘ bigint(20) default NULL, PRIMARY KEY(‘id‘) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Možná si všimnete nepřítomnosti nějakého filtru nebo dalšího rozdělení jednotlivých flow záznamů, i když je něco takového deklarováno jako vstup programu dump2sql. Je to kvůli tomu, že jednotlivé podmínky potom plní samostatné tabulky, respektive výstupem je její jméno. Proč takové řešení? Jednak jsou takto definovaná data jednodušší na údržbu (agregaci), také dotazy nad jednotlivými tabulkami jsou rychlejší, než kdyby byla jedna „obrovskáÿ (předpokládá se velký počet záznamů a zde zmiňovaný rozdíl je znatelný). Další důvod je asi historický vývoj, tato funkcionalita byla implementována jako jedna z posledních a rozdílné jméno tabulky byla nejjednodušší možnost jak data rozdělit. Ukázalo se to zároveň jako dostačující řešení, protože se nepředpokládá, že by se v budoucnu měly generovat statistiky nad daty z několika tabulek.
KAPITOLA 3. ARCHITEKTURA SYSTÉMU
3.3
23
Zobrazování charakteristik
Vizualizaci naměřených dat jsem implementoval v PHP s využitím knihovny gd. Podle zadání měl být využit nějaký GIS (Geograpical Information System), ale už v rané fázi řešení projektu jsme společně s zadavatelem došli k tomu, že bude jednodušším řešením – jednorázově vygenerovaná mapa. GIS jsou většinou pro tyto účely zbytečně složité a také potřebují ke své funkci javascript, javu nebo dokonce flash, což je nevyhovující. Bylo zvoleno zatím šest různých typů zobrazení charakteristik. V každém typu zobrazení si můžete zvolit jaká charakteristika bude zobrazena a časový interval, pro který bude zobrazena. U některých typů zobrazení musíte určit povinně například o jaké zemi se bude charakteristika zobrazovat, nebo třeba můžete specifikovat, kolik prvních zemí se zobrazí. Aktuální typy zobrazení: • mapUsa: zobrazí mapu Spojených států amerických a vybarví jednotlivé státy podle odpovídající velikosti sledované charakteristiky • mapEurope: podobné mapUSA, ale jako mapa je použita mapa Evropy • mapWorld: podobné mapUSA a mapEurope, ale je zobrazená mapa celého světa (vhodné spíše na výřezy) • circle: takzvaný „koláčovýÿ graf • bar: sloupcový graf • oneCountry: vývoj určené charakteristiky v čase pro jednu danou zemi Vstupy zobrazovacího skriptu definujeme následovně. Pokaždé musí být uvedeno jaký typ zobrazení chceme použít, časový interval a vybraná charakteristika. Pokud jsme vybrali typ circle, bar nebo oneCountry, měli bychom specifikovat výšku a šířku výsledné bitmapy, dále v případě oneCountry zemi, v ostatních dvou počet zobrazených zemí (zbytek bude buď reprezentován jako „ostatníÿ (circle) nebo nebude v grafu zahrnut vůbec (bar). V případě vybrání nějaké mapy jako typu zobrazení nebude možno přímo zvolit velikost – vygenerovaný obrázek ji bude mít vždy pevnou, ale můžeme ho přinejhorším lehce zvětšit nebo zmenšit přímo webovým prohlížečem, nebo udělat výřez.
3.4
Skripty pro sběr dat
Součástí mnou vytvořeného systému jsou i skripty pro sběr dat ze všech instancí dump2sql a jejich naimportování do MySQL databáze. Systém sběru dat by měl být odolný vůči výpadkům jak jednotlivých instancí dump2sql, tak i centrální stanice. S výpadkem jedné instance programu problém není, pouze nenávratně přijdeme o data,
24
KAPITOLA 3. ARCHITEKTURA SYSTÉMU
která jí byla poslána. Výpadek centrálního stroje způsobí na druhou stranu pouze hromadění dat na jednotlivých stanicích a pokud nedojde k zaplnění disku před opětovným spuštěním, budou data netknuta, takže výpadek nebude mít žádné následky.
3.5
Další implementační části
V rámci práce na tomto projektu jsem se musel zabývat i úpravou již existujícího softwaru. Bylo efektivnější implementovat nějakou funkcionalitu do již existujícího programu, než ho vyvíjet znovu. Konkrétně se jedná o programy nfdump, samplicator a nprobe.
3.5.1
nfdump
Program nfdump je jméno použité pro celý balík programů, jeden z nich se ale jmenuje nfdump (matoucí, ale je to tak). Tento program slouží k zachytávání datagramů s Netflow záznamy a různému třídění (je podobný program tcpdump). Neumí ale zachytávat pakety, které nejsou určené přímo jemu; neumí tedy naslouchat na určitém rozhraní v promiskuitním módu. Tato funkcionalita se hodila pro kontrolu posílaných dat při implementaci programu dump2sql.
3.5.2
samplicator
Samplicator je program pro přeposílání datagramů. Realizuje tedy jakýsi mirror. Pro účely mého projektu ale bylo spíše potřeba, aby uměl proud datagramů rozdělit na stejně „hutnéÿ proudy a až potom přeposlat. Tuto funkcionalitu jsem doimplementoval, stejně jako naslouchání v promiskuitním módu, které také předtím naimplementováno nebylo. Na kódu tohoto programu je zajímavé, že je psán ve velmi starém dialektu jazyka C, v K&R syntaxi. Naštěstí je stále v i nejnovější verzi gcc podporován, tak nebyl žádný problém s kompilací, pouze s pochopením některých použitých konstrukcí.
KAPITOLA 4. IMPLEMENTACE
25
4 Implementace V této kapitole se budu věnovat popisu implementace, samotných souborů s veškerým kódem a popíšu zde jeho základní rozdělení. Detailní dokumentace vygenerovaná nástrojem doxygen je dostupná na přiloženém médiu. Tato kapitola by neměla být popisem každého řádku kódu, ale měla by dát čtenáři celkový pohled na napsané programy, skripty a celý systém.
4.1
dump2sql
Jak již bylo napsáno dříve, program dump2sql je naimplementován v C/C++. Při volbě programovacího jazyka a celého prostředí tohoto programu byl brán největší ohled na to, že je to jediná část aplikace, která bude pracovat s daty v reálném čase, respektive lépe definováno: bude muset zpracovávat data co nejrychleji. Tomuto požadavku nejlépe vyhovuje jazyk C, ale už během analýzy se ukázalo, že budou potřeba relativně složité datové struktury, jejíž implementace by zabrala spoustu času a není jisté, že by se podařila napsat tak optimálně, jako jsou struktury v knihovně STL dostupné s jazykem C++. Asi nejsložitější požadovanou strukturou je asociativní pole s operacemi vložení, vyhledávání, smazání prvku a iterací přes všechny prvky. Tomuto nejvíce odpovídá šablona map z STL. Když se podíváme na složitost operace, která v programu dump2sql bude využívána nejvíce (vyhledávání), zjistíme, že je specifikována jako log2 (n) (viz například [5]). Odpovídá to použití binárního vyhledávacího stromu nebo podobné pokročilé techniky pro ukládání dat. Vzhledem k tomuto faktu jsem se rozhodl tuto šablonu využít s tím, že program budu psát tak, aby šel bez větších obtíží přepsat do „čistéhoÿ C a zaměnit struktury z STL za vlastní. Kód tohoto programu je rozdělen do několika souborů. • parseconf.h • parseconf.c • support.h • support.cpp • main.h • main.cpp Soubory parseconf.h a parseconf.c jsou přejaty z projektu MAPI. Implementují zpracování konfiguračních souborů ve formátu typicky používaném v ini souborech v programech pro operační systém Windows. Zde je tento formát použit na zadávání uživatelských filtrů, respektive na zpracování souboru, kde jsou takto zadané filtry zadány.
26
KAPITOLA 4. IMPLEMENTACE
Obrázek 4.1: Závislosti souboru parseconf.c
Z obrázku 4.1 je vidět, že celá součást na zpracování konfigurace je závislá pouze na standardně dostupných knihovnách jazyka C, takže by neměl být problém s funkčností nebo překladem této komponenty. Soubory support.h a support.cpp jsou už regulérní součást programu dump2sql. Mám tím na mysli, že tento kód není odnikud převzatý. V support.h naleznete nadeklarované pomocné funkce, jako například převod mezi jednotlivými datovými typy, získání IP adresu z bitové reprezentace nebo univerzální logovací funkci.
Obrázek 4.2: Závislosti souboru support.cpp Na obrázku 4.2 jsou uvedeny soubory vkládané touto částí programu. Většina z nich je z STL, ale mohla by být nahrazena vlastními. Jak již bylo řečeno dříve, je toto pouze podpůrná množina funkcí, tedy neobsahuje žádný zajímavý algoritmus. Za pozornost ale stojí například použití šablony bitset k převodu binární reprezentace IP adresy na řetězec a logovací funkce. Logovací funkce je volána při každém výstupu programu (mimo exportovaných souborů), tj. k standardnímu výstupu se přistupuje pouze přes ni. Má to výhodu v absolutní kontrole, což se hodí například v přepnutí zaznamenávání operací do syslogu při běhu jako systémová služba nebo k možné implementaci dalších variant (například posílání důležitých zpráv emailem nebo i SMS zprávou). Další skutečnost hodná pozornosti jsou funkce pro převod mezi datovými typy. Proč? Nejdříve jsem je měl implementované s použitím šablony stringstream z STL. Použití je elegantní, protože tato šablona se o převod stará víceméně sama a při převodech základních typů není třeba moc přemýšlet. Pokud bych chtěl například převést řetězec na kladné celé číslo, vypadal by kód následovně:
KAPITOLA 4. IMPLEMENTACE
27
unsigned int str2int(string str) { stringstream ss; unsigned int num; ss << str; ss >> num; return num; }
Bohužel má ale tento postup jednu chybu. Ona to není ani tak chyba, jako vlastnost, každopádně je to ale v tomto programu nepoužitelné. Nevím přesně, jakým algoritmem knihovna STL v uvedeném případě převádí obsah stringstreamu do daného typu, vím ale určitě, že je tento postup nejméně dvakrát pomalejší než prosté zavolání funkce atoi ze stdlib.h. Vzhledem k tomu, že funkce pro převod v programu volám pro každý přijatý datagram několikrát, mělo toto zpomalení vliv na celkový výkon programu. Odhalil jsem ho až v rámci konečného testování a profilingu, při výkonové optimalizaci. Plyne z toho jednoduché poučení: „Ne všechny elegantní postupy jsou optimálníÿ. Zbývají už pouze soubory main.h a main.cpp. V nich je obsažené funkční jádro celého programu dump2sql. Budu se snažit ho probrat trochu podrobněji než předchozí dvě součásti, ale zase nechci vysvětlovat kód řádek po řádku. Bohužel se sem nevejde graf závislostí, jako u předchozích případů, je příliš široký, ale obecně jsou do tohoto souboru vloženy všechny hlavičkové soubory z support.h, dále soubor definující rozhraní ke knihovně GeoIP a soubory nutné pro práci se síťovým rozhraním a s tím související hlavičkový soubor knihovny libpcap. K demonstraci funkcionality a struktury programu jsem zvolil dvě různé varianty. Vývojový diagram (obr. 4.3) a graf volání funkcí (call graph, obr. 4.4). Ve vývojovém diagramu je zobrazeno několik základních bloků programu, bez větších detailů. Ukazuje ale hlavní myšlenku a schéma odpovídá klasickému schématu systémové služby (daemona). Program v nekonečném cyklu přijímá datagramy a pokud uplynul definovaný časový interval, vytvoří podproces, který exportuje data do textového souboru. Na první pohled je nejspíš obrázek 4.4 ne příliš přehledný, ale zkusme si ho rozebrat. Vlevo je vstupní funkce celého programu, funkce main (jako ve všech programech). Dále od ní vedou orientované šipky k funkcím, které přímo volá. Když začneme od spodní části obrázku, můžeme si všimnout třech „podstromůÿ. Funkce tokenize a funkce s prefixem pc slouží k načítání a zpracování vstupů (tokenize rozděluje řetězce podle daného kritéria a funkce s prefixem pc slouží ke zpracování konfiguračního souboru, který je tu použit k nastavení filtrů). Funkce sigint slouží jako obsluha signálu, který program dostane například při stisku kláves ctrl a c. Funkce main tedy pouze zpracuje všechny vstupy a předá řízení dál. Tímto jsme odbyli relativně nezajímavé funkce a na obrázku zbylo pouze volání funkce daemon main. Pokud se podíváme na podstrom právě této funkce, začne to být trochu matoucí. Je to díky tomu, že je celkem dost funkcionality implementováno přímo v této funkci a v call grafu tím pádem není vidět. Pro pochopení nám stačí podívat se zpět do kapitoly popis problému, kde je implementace tohoto programu rozdělena na pět částí.
28
KAPITOLA 4. IMPLEMENTACE
Obrázek 4.3: Vývojový diagram programu dump2sql
První z nich, zachycení datagramu, je implementováno přímo ve funkci daemon main. Je vhodné zmínit, že je implementováno buď jako standardní přijetí UDP datagramu, nebo pomocí knihovny. Dále je na řadě zpracování zachyceného datagramu, co čehož spadá uložení případných šablon a získání dat v něm obsažených. Získání dat zastane funkce daemon main, ale pouze je uloží do dočasného asociativního pole a předá ho jako parametr funkci processLine. Jen pro upřesnění – funkce processLine je volána pro každý rozpoznaný flow záznam. ProcessLine má na starost samotnou geografickou lokalizaci, tj. právě v ní je realizováno volání funkcí knihovny GeoIP. Také je zde zjištěn určen čas a dále lokalizovány vektory ve struktuře trafficMap (je popsaná v kapitole Analýza), do kterých se zpracovávaný flow bude přidávat. Není zde ale realizováno přímo vložení, jen se předají potřebné parametry další funkci, konkrétně updateTrafficMap, která se stará pouze o korektní přetypování a samotné zařazení do již určených vektorů. Je také vhodné poznamenat, že každý flow je uložený dvakrát. Jednou jako výstupní z určené země, podruhé jako vstupní. To platí i když jsou obě stejné (například flow z České republiky do České republiky je zaznamenaný jednou jako vstup a podruhé jako výstup). Další podstrom vedoucí z funkce daemon main je processTrafficMap. Tato funkce je volaná jednou za daný interval a exportuje všechna data uložená ve struktuře trafficMap do souboru v daném formátu. Nejdříve je však agreguje (sečte vždy všechny hodnoty v daném intervalu (5 minut) a až tuto informaci exportuje. Je to kvůli velkému počtu zpracovaných záznamů. Pokud by tato agregace nebyla provedena, byla by extrémně zatěžována MySQL databáze, do které se data následně uloží. Funkce processTrafficMap funguje tedy tak, že vytvoří prázdnou strukturu aggregatedTrafficMap a do ní nakopíruje již agregovaná data (která získá postupným procházením struktury trafficMap).
KAPITOLA 4. IMPLEMENTACE
29
Obrázek 4.4: Call graph programu dump2sql
Tu potom také projde, ale tentokrát na každý záznam zavolá funkci createMySQLQuery, která ze záznamu vytvoří SQL dotaz. Ten je poté pouze uložen do souboru. Mohlo by se zdát, že je export celkem náročná procedura a ona i je. Proto jsou tyto operace prováděny v separátním procesu, aby hlavní proces mohl neustále zachytávat další datagramy. Přesněji se při každém exportu program rozdělí na dva procesy. V jednom se pouze smaže struktura trafficMap a program pokračuje ve své primární funkci, v druhém se provede export a proces skončí.
4.2
Zobrazování charakteristik a agregace dat
Jak již bylo řečeno, generování grafického výstupu je realizováno ve skriptovacím jazyce PHP a samotné vykreslování je implementováno pomocí knihovny gd. Kód je opět rozdělen do několika souborů.
• common.php
30
KAPITOLA 4. IMPLEMENTACE • dbInterface.php • allInOne.php • dbAgregate.php
Soubor common.php obsahuje podpůrné funkce a datové struktury. Ze struktur to je například pole, ve kterém jsou uvedeny zkratky a jejich nezkrácené všech zemí světa, také jednotlivých státu Spojených státu amerických. Z funkcí obsahuje například funkce s prefixem getColor, které vrací barvu například v závislosti na státu, nebo na aktuální a maximální hodnotě. Také jsou zde přítomné funkce pro zaokrouhlování a kontrolu vstupních parametrů. V souboru dbInterface.php je soustředěna veškerá komunikace s MySQL databází. Pokud by se nějak změnilo úložiště dat, stačí změnit kód funkcí zde implementovaných a zobrazovací skript bude fungovat stejně. V tomto souboru jsou tedy funkce pro připojení do databáze a získaní hodnot z ní. Žádné další funkce nejsou potřeba, zobrazovací skript nikdy do databáze nezapisuje. Soubor allInOne.php je tím, který zobrazujeme v prohlížeči, když chceme vidět určitou charakteristiku. Vstupní parametry jsou opět uvedeny v kapitole Analýza. Zobrazovací skripty nejsou celkem ničím zajímavé ani složité, jedná se vlastně pouze o získání dat a volání funkcí knihovny gd pro zápis dat do obrázku. Nebudu se jim zde tedy věnovat a zájemce o podrobnosti odkáži na komentáře ve zdrojových kódech těchto skriptů.
Obrázek 4.5: Ukázka typu zobrazení charakteristik – bar Skrip v souboru dbAgregate.php slouží, jak je již z názvu nejspíš patrné, k agregaci dat v databázi. Původně to byl skript spouštěný prohlížečem, ale během implementace se změnil na skript spouštěný z příkazové řádky, protože to usnadní jeho plánované periodické spouštění. Vývoj byl i ve zpracování informací, tedy v postupu samotné agregace. První idea byla taková, že skript vybral všechna data, která měla být agregována, uložil je do paměti, smazal z databáze a pak uložil agregovaná. Tento postup fungoval dobře, ale pouze pokud databáze neobsahovala moc velký počet záznamů. Celý proces se teď
KAPITOLA 4. IMPLEMENTACE
31
Obrázek 4.6: Ukázka typu zobrazení charakteristik – circle
provádí po nejmenších intervalech, aby nedošlo k podobným problémům. Má to také výhodu v tom, že když proces s běžícím skriptem z nějakých důvodů „umřeÿ, bude ztraceno minimální množství dat (v prvním případě by byla ztracena všechna agregovaná data). Agregace (jako proces) má následující vstupní hodnoty: časový interval, na jakou jednotku se má agregovat a jméno tabulky, na které se má agregace provést (a samozřejmě údaje nutné k přípojení databáze). Jak jsem již zmínil, skript je spustitelný z příkazové řádky. Jazyk PHP potom není z hlediska výkonu ideální volba, ale mám za to, že není třeba systém komplikovat dalším programovacím jazykem (na tuto úlohu by byl vhodnější perl nebo python).
32
KAPITOLA 4. IMPLEMENTACE
Obrázek 4.7: Ukázka typu zobrazení charakteristik – mapEurope
Obrázek 4.8: Ukázka typu zobrazení charakteristik – mapUSA
KAPITOLA 5. TESTOVÁNÍ
33
5 Testování Program jsem během celého vývoje testoval. Nejdříve to byly jednoduché testy stability a správné práce s pamětí – nechal jsem program běžet několik dní a sledoval jsem, jak se mění zabraná paměť s časem. Dokud se mi nepodařilo docílit konstantního průběhu, studoval jsem nástrojem memcheck z balíku valgrind neuvolněnou paměť. Takto se podařilo docílit skoro konstantního záboru paměti, respektive zabraná paměť je závislá na počtu momentálně držených flow záznamů. Program je tedy stabilní a zdá se, že všechnu paměť uvolňuje správně (program běží déle než měsíc a paměť jemu přidělená se nezvyšuje). Poté následovaly první testy na propustnost. První test byl zaměřen na určení maximální možné propustnosti, kde jsem se zaměřil na knihovnu GeoIP. Napsal jsem jednoduchý program, který se kontinuálně ptal na lokaci náhodně generovaných IP adres. Pomocí aplikačního rozhraní v jazyce C se mi podařilo průměrně uskutečnit 159 108 dotazů za minutu, kdy změřená propustnost tehdejší verze aplikace dump2sql byla 12 864 flow záznamů za minutu (to je 25 728 dotazů, protože pro každý flow záznam se zjišťuje lokace zdroje i cíle). Cílem tohoto měření bylo zjistit, zda je výkon programu dump2sql limitován výkonem knihovny GeoIP, nebo zda je úzké hrdlo někde jinde. Z naměřených výsledků vyplynulo, že problém byl někde jinde a že aplikační rozhraní knihovny GeoIP nemělo rozhodující vliv na výkon celého programu. Bohužel nemám zaznamenáno na jakém stroji jsem měření prováděl, takže tato čísla jsou pouze informativní. Další testy jsem prováděl až na aktuální verzi pro určení celkové výkonnosti systému a profilování napsaného kódu. První věcí, kterou jsem udělal pro získání maximálního výkonu, bylo zapnutí optimalizací překladače. Zapl jsem všechny optimalizace, které gcc/g++ umí, tj. přidal jsem parametr –O3. Další krok bylo použití programu valgrind, tentokrát ale modul callgrind. Výsledek běhu je možno zobrazit programem kcachegrind, který přehledně zobrazí všechna volání a strávený čas v jednotlivých funkčních voláních. Výhoda tohoto postupu je v tom, že program není potřeba nějak speciálně kompilovat. Pomocí tohoto programu se mi podařilo najít snad většinu neoptimálního kódu a minimalizovat počet instrukcí pro vykonání funkcí, které se opakovaly nejčastěji. Po této upravě následovalo nové měření propustnosti. Měřil jsem tentokrát jinou veličinu – ne zpracované flow, ale přijaté datagramy. Je to kvůli tomu, že jsem si mohl jednoduše do programu samplicator implementovat čítač paketu, ale čítač flow záznamů by byl složitější a do samplicatoru nehodící-se. Problém je potom ještě s tím, kde datagramy získávat, když živý provoz dokáže systém zpracovat relativně bez obtíží. Jedno z řešení je vytvořit navíc generátor flow záznamů, který by generoval trvalý proud datagramů s flow záznamy. Přesně takový jsem v rámci testování naimplementoval. Problémů s takovým umělým testem je hned několik. Například generování IP adres, dále třeba jaký formát flow zvolit a kolik flow záznamů má být v jednom odesílané datagramu. Snažil jsem se mít generátor co nejjednodušší a přesto výsledky co nejprůkaznější a zvolil jsem následující parametry: IP adresy se generují pseudonáhodně, je použita relativně jednoduchá šablona a obsahuje tolik dat, aby se do
34
KAPITOLA 5. TESTOVÁNÍ
Obrázek 5.1: KCacheGrind
datagramu vešlo přesně padesát flow záznamů. Všechna ostatní data jsou generována také pseudonáhodně.
5.1
Výsledky měření
Maximální propustnost programu dump2sql jsem testoval na stroji opc1.cesnet.cz, na kterém mi byl v rámci vývoje projektu poskytnut přístup. Je to multiprocesorový systém bežící na operačním systému Linux, konkrétně Debian s jádrem ve verzi 2.6.16.9. Stroj je osazen čtyřmi procesory Intel(R) Xeon(TM) operujícími na frekvenci 3.20 GHz a 896 MB RAM. Vzhledem k počtu procesorů jsem zkusil otestovat i škálovatelnost tohoto řešení, viz tabulka 5.1. Jeden samostatně běžící proces dokázal zpracovat průměrně 5205 datagramů za minutu, což je zhruba 260 tisíc flow záznamů za minutu. Když jsem tok generovaných datagramů rozdělil programem samplicator na dvě instance, dokázalo se zpracovat průměrně 4129 + 3984 = 8113 datagramů za minutu. Pokud tento údaj přepočteme na flow záznamy, vyjde cca 405 tisíc flow záznamů za minutu. Zkusil jsem rozdělit tok i na tři instance a naměřená propustnost byla 3290 + 3105 + 3149 = 9544 datagramů za minutu, což odpovídá 477 tisícům flow záznamům za minutu. Když si spočítáme zvětšení počtu zpracovaných flow vůči situaci s jedním samostatným procesem, vyjde zrychlení při přidání jednoho procesu 1,5 a při přidání dvou procesů je to 1,8. To nejsou moc povzbudivá čísla, zvlášť když teoreticky by mělo být zrychlení rovno
KAPITOLA 5. TESTOVÁNÍ Počet instancí 1 2 3
Zpracovaných datagramů datagram za minutu 5 205 8 113 9 544
35 Zpracovaných flow záznamů flow za minutu 260 000 405 000 477 000
Tabulka 5.1: Měření propustnosti datagramů počtu instancí. Důvody, proč se podařilo naměřit to co se podařilo naměřit mohou být různé, mě jako první napadl vliv velkého počtu přístupů na disk při lokalizaci pomocí knihovny GeoIP. Po několika měřeních jsem ale zjistil, že zde úzké hrdlo není, celý soubor s databází (21 MB) se při používání uloží v cache a systém vůbec na disk nepřistupuje. Jako další variantu možného zpoždění mě napadl průchod datagramů přes iptables, při vyhodnocování několika pravidel by mohla být propustnost při testovacích tocích ovlivněna. Bohužel jsem něměl prostor pro otestování, respektive něměl jsem před dokončením této práce k dispozici víceprocesorový stroj na kterém bych mohl iptables zcela vypnout. Udělal jsem ale analýzu pomocí programu strace, která teoreticky mohla odhalit místo, kde se stráví při běhu několika instancích více času. Podle měření to bylo při volání funkce select, ale rozdíl nebyl tak signifikantní, aby vysvětloval zpoždění naměřené v tabulce 5.1.
36
KAPITOLA 6. ZÁVĚR
6 Závěr V rámci této práce jsem vytvořil systém pro zpracování charakteristik o síťovém provozu získávaných z flow záznamů, lokalizování jednotlivých účastníků spojení a zobrazení charakteristik takto získaných dat. Vytvořil a otestoval jsem stabilní systém, který dokáže bez údržby běžet týdny. Jediný rozpor se zadáním práce je nepoužití žádného GIS, ale tento požadavek byl během realizace projektu upraven a bylo použito efektivnější řešení. Výsledek této práce se dá využít k plánování globálního rozvoje hlavně serverové infrastruktury, k čemuž právě mohou sloužit statistiky vztažené k jednotlivým zemím. Také se může využít jako podklad při plánování rozšíření internetové konektivity a samozřejmě k monitorování charakteristik různých internetových spojů. Celý systém bude nasazen na CESNETu k monitorování spojů do sítí NIX a GÉANT2. Další vývoj celého řešení vidím v optimalizaci již napsaného kódu a přidávání zaznamenávaných charakteristik naimplementováním funkcionality do programu nprobe. Momentálně je nejžádanější implementace maximální, minimální a průměrné hodnoty RTT (Round Trip Time). Prostor pro vylepšení je také u generovaných grafů, ať už se jedná o grafickou podobu nebo o způsoby zobrazování jednotlivých statistik.
KAPITOLA 7. LITERATURA
7 Literatura [1] Cisco IOS Netflow version 9 flow-record format http://www.cisco.com/warp/public/cc/pd/iosw/prodlit/tflow_wp.htm [2] History of the Internet, Internet for Historians http://www.let.leidenuniv.nl/history/ivh/ [3] Cybertelecom – federal internet law & policy – an educational project http://www.cybertelecom.org/notes/internet_history.htm [4] An IPFIX-based file format draft-trammell-ipfix-file-05 http://tools.ietf.org/html/draft-trammell-ipfix-file-05 [5] Referenční příručka jazyka C++ http://www.cplusplus.com/ [6] RFC editor homepage http://www.rfc-editor.org/ [7] Wikipedia, the free encyklopedia http://en.wikipedia.org
37
38
KAPITOLA 7. LITERATURA
PŘÍLOHA A. SEZNAM POUŽITÝCH ZKRATEK
A Seznam použitých zkratek AfriNIC African Region Internet Registry AHHP ARPANet Host to Host Protocol APNIC Asia-Pacific Network Information Centre ARIN American Registry for Internet Numbers ARP Address Resolution Protocol ARPA Advanced Research Project Agency ASCII American Standard Code for Information Interchange AS Autonomous System ASO Address Supporting Organization B2B Business to Business Bash GNU Bourne Again SHell BBS Bulletin Board System BGP Border Gateway Protocol CCNSO Country Code Names Supporting Organization DHCP Dynamic Host Configuration Protocol DISA Defence Communications Agency DNS Domain Name System / Domain Name Service FTP File Transfer Protocol gcc GNU Compiler Collection GIS Geographical Information System HDLC High-Level Data Link Control IANA Internet Assigned Numbers Authority ICANN Internet Corporation for Assigned Names and Numbers ICMP Internet Control Message Protocol ICP Initial Connection Protocol IMAP Internet Message Access Protocol IMP Interface Message Processor
39
40
PŘÍLOHA A. SEZNAM POUŽITÝCH ZKRATEK
IP Internet Protocol IPFIX IP Flow Infromation eXport Protocol ISOC Intergalactic Computer Network LACNIC Latin American and Caribbean Internet Addresses Registry MIT Massachusetts Institute of Technology NASA National Aeronautics and Space Administration NAT Network Address Translation NIX Neutral Internet Exchange MMORPG Massive Multiplayer Online Role Playing Game MUD Multi User Dungeon NCP Network Control Program NRO Number Resource Organization NSF National Science Foundation OSPF Open Shortest Path First POP Post Office Protocol PPP Point-to-Point Protocol RAM Random Access Memory RARP Reverse Address Resolution Protocol RFC Request For Comment RIP Routing Information Protocol RIPE R`eseaux IP Europ`eens RIPE NCC RIPE Network Coordination Centre RIR Regional Internet registry RTT Round Trip Time SCTP Stream Control Transmission Protocol STL Standard Template Library SMTP Simple Mail Transfer Protocol SQL Structured Query Language
PŘÍLOHA A. SEZNAM POUŽITÝCH ZKRATEK TCP Transmission Control Protocol TLD Top Level Domain UCLA University of California, Los Angeles UCSB University of California, Santa Barbara UDP User Datagram Protocol
41
42
PŘÍLOHA A. SEZNAM POUŽITÝCH ZKRATEK
PŘÍLOHA B. DEFINICE TYPŮ POUŽITELNÝCH V NETFLOW VERZE 9
B Definice typů použitelných v NetFlow verze 9 Field Type
IN_BYTES
Value Length Description (bytes)
1
N
Incoming counter with length N x 8 bits for the number of bytes associated with an IP Flow. By default N is 4 Incoming counter with length N x 8 bits for the number of packets associated with an IP Flow. By default N is 4
IN_PKTS
2
N
FLOWS
3
N
Number of Flows that were aggregated; by default N is 4
PROTOCOL
4
1
IP protocol byte
TOS
5
1
Type of service byte setting when entering the incoming interface
TCP_FLAGS
6
1
TCP flags; cumulative of all the TCP flags seen in this Flow
L4_SRC_PORT
7
2
TCP/UDP source port number (for example, FTP, Telnet, or equivalent)
IPV4_SRC_ADDR
8
4
IPv4 source address
SRC_MASK
INPUT_SNMP
9
10
1
N
The number of contiguous bits in the source subnet mask (i.e., the mask in slash notation) Input interface index. By default N is 2, but higher values can be used
43
44
PŘÍLOHA B. DEFINICE TYPŮ POUŽITELNÝCH V NETFLOW VERZE 9
L4_DST_PORT
11
2
TCP/UDP destination port number (for example, FTP, Telnet, or equivalent)
IPV4_DST_ADDR
12
4
IPv4 destination address
DST_MASK
13
1
The number of contiguous bits in the destination subnet mask (i.e., the mask in slash notation) Output interface index.
OUTPUT_SNMP
14
N
By default N is 2, but higher values can be used
IPV4_NEXT_HOP
15
4
IPv4 address of the nexthop router
SRC_AS
16
N
DST_AS
17
N
BGP_IPV4_NEXT_HOP
18
4
MUL_DST_PKTS
19
N
MUL_DST_BYTES
20
N
LAST_SWITCHED
21
4
Source BGP autonomous system number where N could be 2 or 4. By default N is 2 Destination BGP autonomous system number where N could be 2 or 4. By default N is 2 Next-hop router’s IP address in the BGP domain IP multicast outgoing packet counter with length N x 8 bits for packets associated with the IP Flow. By default N is 4 IP multicast outgoing Octet (byte) counter with length N x 8 bits for the number of bytes associated with the IP Flow. By default N is 4 sysUptime in msec at which the last packet of this
PŘÍLOHA B. DEFINICE TYPŮ POUŽITELNÝCH V NETFLOW VERZE 9 Flow was switched
FIRST_SWITCHED
OUT_BYTES
22
23
4
sysUptime in msec at which the first packet of this Flow was switched
N
Outgoing counter with length N x 8 bits for the number of bytes associated with an IP Flow. By default N is 4
OUT_PKTS
24
N
Outgoing counter with length N x 8 bits for the number of packets associated with an IP Flow. By default N is 4
IPV6_SRC_ADDR
27
16
IPv6 source address
IPV6_DST_ADDR
28
16
IPv6 destination address
IPV6_SRC_MASK
29
1
Length of the IPv6 source mask in contiguous bits
IPV6_DST_MASK
30
1
IPV6_FLOW_LABEL
31
3
ICMP_TYPE
32
2
MUL_IGMP_TYPE
33
1
SAMPLING_INTERVAL
34
4
Length of the IPv6 destination mask in contiguous bits IPv6 flow label as per RFC 2460 definition Internet Control Message Protocol (ICMP) packet type; reported as ICMP Type * 256 + ICMP code Internet Group Management Protocol (IGMP) packet type When using sampled NetFlow, the rate at which packets are sampled; for example, a value of 100 indicates that one of every hundred packets is sampled
45
46
PŘÍLOHA B. DEFINICE TYPŮ POUŽITELNÝCH V NETFLOW VERZE 9
SAMPLING_ALGORITHM
35
1
FLOW_ACTIVE_TIMEOUT
36
2
For sampled NetFlow platform-wide: 0x01 deterministic sampling 0x02 random sampling Use in connection with SAMPLING_INTERVAL Timeout value (in seconds) for active flow entries in the NetFlow cache
FLOW_INACTIVE_TIMEOUT
37
2
Timeout value (in seconds) for inactive Flow entries in the NetFlow cache
ENGINE_TYPE
38
1
Type of Flow switching engine (route processor, linecard, etc...)
ENGINE_ID
39
1
TOTAL_BYTES_EXP
TOTAL_PKTS_EXP
40
41
ID number of the Flow switching engine
N
Counter with length N x 8 bits for the number of bytes exported by the Observation Domain. By default N is 4
N
Counter with length N x 8 bits for the number of packets exported by the Observation Domain. By default N is 4 Counter with length N x 8 bits for the number of Flows exported by the Observation Domain. By default N is 4
TOTAL_FLOWS_EXP
42
N
MPLS_TOP_LABEL_TYPE
46
1
MPLS 0x00 0x01 0x02 0x03 0x04 0x05
Top Label Type: UNKNOWN TE-MIDPT ATOM VPN BGP LDP
PŘÍLOHA B. DEFINICE TYPŮ POUŽITELNÝCH V NETFLOW VERZE 9
MPLS_TOP_LABEL_IP_ADDR
47
4
FLOW_SAMPLER_ID
48
1
FLOW_SAMPLER_MODE
Forwarding Equivalent Class corresponding to the MPLS Top Label Identifier shown in "show flow-sampler" The type of algorithm used for sampling data: 0x02 random sampling Use in connection with FLOW_SAMPLER_MODE Packet interval at which to sample. Use in connection with FLOW_SAMPLER_MODE
49
1
FLOW_SAMPLER_RANDOM_INTERVAL 50
4
DST_TOS
55
1
Type of Service byte setting when exiting outgoing interface
SRC_MAC
56
6
Source MAC Address
DST_MAC
57
6
Destination MAC Address Virtual LAN identifier
SRC_VLAN
58
2
associated with ingress interface
DST_VLAN
59
2
Virtual LAN identifier associated with egress interface
IP_PROTOCOL_VERSION
60
1
Internet Protocol Version Set to 4 for IPv4, set to 6 for IPv6. If not present in the template, then version 4 is assumed
DIRECTION
61
1
Flow direction: 0 - ingress flow 1 - egress flow
IPV6_NEXT_HOP
62
16
IPv6 address of the next-hop router
47
48
PŘÍLOHA B. DEFINICE TYPŮ POUŽITELNÝCH V NETFLOW VERZE 9 BGP_IPV6_NEXT_HOP
63
16
Next-hop router in the BGP domain Bit-encoded field identifying IPv6 option headers found in the flow
IPV6_OPTION_HEADERS
64
4
MPLS_LABEL_1
70
3
MPLS label at position 1 in the stack
MPLS_LABEL_2
71
3
MPLS label at position 2 in the stack
MPLS_LABEL_3
72
3
MPLS label at position 3 in the stack
MPLS_LABEL_4
73
3
MPLS label at position 4 in the stack
MPLS_LABEL_5
74
3
MPLS label at position 5 in the stack
MPLS_LABEL_6
75
3
MPLS label at position 6 in the stack
MPLS_LABEL_7
76
3
MPLS label at position 7 in the stack
MPLS_LABEL_8
77
3
MPLS label at position 8 in the stack
MPLS_LABEL_9
78
3
MPLS label at position 9 in the stack
MPLS_LABEL_10
79
3
MPLS label at position 10 in the stack
PŘÍLOHA C. OBSAH PŘILOŽENÉHO MÉDIA
C Obsah přiloženého média • zdrojové kódy programu dump2sql • skripty na zobrazení charakteristik • skripty pro přenos dat od instancí programu dump2sql do centrální databáze • zdrojové kódy generátoru netflow záznamů (použit při testování) • upravený program samplicator • upravený program nfdump • zdrojové kódy knihovny GeoIP • zdrojové kódy knihovny libpcap • instalační manuál a popis zprovoznění celého systému • popis parametrů všech mnou implementovaných programů • zdrojové kódy tohoto dokumentu a jeho přeložená verze
49