1 E07/ELO/09 Diepenbeek, 2007 Emulatie van Traffic Control in User-Mode Linux rapport over het eindwerk van Geert GERITS en Filip SCHREURS kandidaten ...
rapport over het eindwerk van Geert GERITS en Filip SCHREURS kandidaten voor de graad van industrieel ingenieur in de elektronica
Promotor: ing. L. Rutten
Woord vooraf Via deze weg willen we graag enkele personen bedanken die ons hebben geholpen om dit eindwerk tot een goed einde te brengen. In de eerste plaats is dat onze promotor, meneer L. Rutten, die ons het hele jaar door goed heeft bijgestaan. Zonder zijn hulp zouden we nooit zo ver geraakt zijn als nu het geval is. Vervolgens willen we ook mevrouw M. Mussen bedanken voor de taalkundige revisie. Verder danken we zeker ook onze ouders voor de morele en financiële steun. Zonder hen was het niet mogelijk geweest om dit eindwerk, en onze studies in het algemeen, te voltooien. Tot slot willen we nog meedelen dat dit document gemaakt is in DocBook volgens het DocBook XML DTD V4.5. Voor de opmaak hebben we gebruik gemaakt van een aangepaste versie van de XSL-stylesheets voor DocBook-XML-bestanden v1.72.0 van Norman Walsh. Voor meer info, zie bijlage A.
Lijst van figuren 2.1 Vergelijking tussen UML en Qemu .......................................................................................... 9 2.2 Screenshot van een menuconfig ............................................................................................. 12 3.1 Schema van het OSI-model .................................................................................................... 15 3.2 Schema van het virtuele netwerk ............................................................................................ 18 4.1 Schematische voorstelling van het voorbeeldnetwerk ............................................................. 20 4.2 Hiërarchische structuur van een MIB ..................................................................................... 21 4.3 Schematische weergave van een eenvoudige circulaire database ............................................. 23 4.4 Schematische weergave van de RRDtool-database ................................................................. 25 4.5 Voorbeeldgrafiek met 2 uren aan data .................................................................................... 27 4.6 Voorbeeldgrafiek met 24 uren aan data .................................................................................. 28 4.7 Voorbeeldgrafiek met 7 dagen aan data ................................................................................. 28 4.8 Voorbeeldgrafiek met 30 dagen aan data ................................................................................ 28 5.1 Schematische voorstelling van het voorbeeldnetwerk ............................................................. 29 5.2 Schema van de instellingen van HTB: rate en ceil .................................................................. 30 5.3 Grafiek van een download, begrensd met een rate .................................................................. 31 5.4 Grafiek van een download, begrensd met een rate en een ceil ................................................. 32 5.5 Schema van de instellingen van HTB: meerdere klassen ........................................................ 32 5.6 Grafiek van een HTTP-download ........................................................................................... 34 5.7 Grafiek van een FTP-download .............................................................................................. 34 5.8 Schema van de instellingen van HTB: burst ........................................................................... 35 5.9 Grafiek van een download, zonder burst ................................................................................ 36 5.10 Grafiek van een download, geboost door een burst ............................................................... 36 7.1 Algemeen schema van het virtuele netwerk in de testopstelling .............................................. 56
Abstract Het doel van dit eindwerk is een testomgeving ontwerpen met behulp van User-Mode Linux. Deze testomgeving moet in staat zijn om een volledig virtueel netwerk te emuleren op één enkele pc. De gebruiker moet het dataverkeer in deze testomgeving eenvoudig kunnen nagaan en indien nodig ook controleren. User-Mode Linux laat toe verschillende virtuele Linuxsystemen als een applicatie te draaien binnen een bestaand Linuxsysteem. Hierdoor leent het zich uitstekend om nieuwe software uit te testen en te debuggen zonder dat het het huidige systeem beïnvloedt. User-Mode Linux kan meerdere virtuele systemen tegelijk aanmaken die in hardware en software verschillen van de gebruikte pc. Met deze virtuele systemen emuleren we een netwerk dat dienst kan doen als testomgeving voor verschillende programma's, technieken en protocols. Een eerste belangrijke techniek is Hierarchical Token Bucket (HTB), een onderdeel van Traffic Control (tc). HTB is een eenvoudige maar krachtige techniek waarmee we het dataverkeer over het netwerk kunnen controleren en limiteren. Een tweede techniek is RRDtool. Deze kan met behulp van het Simple Network Management Protocol (SNMP) gegevens opvragen bij een router en deze opslaan in een database. Het kan vervolgens van de opgeslagen gegevens grafieken genereren die we tot in de details kunnen configureren. Met behulp van een Apache webserver publiceren we de grafieken op een eenvoudige website. Na de testfase kan de virtuele testomgeving dienst doen als netwerkdemo om de werking van de verschillende uitgeteste technieken duidelijk te maken. Ze kan zo een nuttige aanvulling zijn voor de lessen datacommunicatie. En door de realistische emulatie in User-Mode Linux levert de overgang van testsysteem naar reëel systeem zelden grote problemen op.
Hoofdstuk 1: Inleiding De dag van vandaag is open-sourcesoftware aan een grote opmars bezig. Denk maar aan het besturingssysteem Linux dat voor meer en meer gebruikers het standaardbesturingssysteem is geworden. Of denk aan Sun's kantoorpakket OpenOffice.org, dat niet enkel voor Linux, maar ook voor andere besturingssystemen een goed alternatief is voor de vaak dure kantoortoepassingen. Zowel verschillende Linuxdistributies als het volledige OpenOffice.org-pakket zijn volledig gratis en legaal te downloaden van het internet.
1.1 Open-sourcesoftware Open-sourcesoftware (soms ook open-bronsoftware genoemd) is computerprogrammatuur waarvan de broncode in te kijken en te veranderen is [1]. De gebruiker kan, met andere woorden, de software zelf aanpassen als hij niet geheel tevreden is met de werking ervan. De voorwaarde is wel dat hij over genoeg kennis moet beschikken om de broncode te begrijpen en op een correcte manier aan te passen. Dit is een groot voordeel ten opzichte van commerciële software, waar de broncode vaak een bedrijfsgeheim is. Als er in deze software een fout zit, of de werking is verouderd of niet meer volgens de huidige wetten en reglementen, dan moet de gebruiker de leverancier inschakelen om hier iets aan te doen. De gebruiker heeft vaak geen invloed meer over de snelheid waarop de leverancier de software aanpast. Het kan zelfs zijn dat de leverancier besluit om de ontwikkeling volledig stop te zetten. In zo'n geval moet er gezocht worden naar een waardig alternatief, wat mogelijk een hele boel onverwachte kosten met zich mee brengt. Het is niet omdat gebruikers open-sourcesoftware zelf kunnen aanpassen dat de ontwikkelaars er zich niet meer mee bezighouden. In vele gevallen zullen er voor open-sourcesoftware ook updates worden gemaakt, net zoals bij alle andere software. In sommige gevalen bieden de ontwikkelaars zelfs een bepaalde vorm van ondersteuning en garanties aan hun gebruikers aan. Het gaat dan meestal niet over gratis software. Dit is bijvoorbeeld het geval bij een aantal distributies van het besturingssysteem Linux. Bedrijven die willen overschakelen op Linux willen bepaalde garanties dat de overschakeling geen al te grote problemen veroorzaakt. En ze willen garanties dat de ontwikkelaars het besturingssysteem op regelmatige tijden updaten, vooral als gebruikers fouten ontdekken.
1.2 Emulatie Een emulator maakt het mogelijk om een ander of verouderd computersysteem in een eigen of nieuwe omgeving na te bootsen [2]. Emulatie wordt vaak verward met simulatie, hoewel er toch een duidelijk verschil is. Een simulatie beschrijft enkel wat iets anders doet of hoe het werkt, terwijl een emulatie datgene ook daadwerkelijk uitvoert. Een vliegtuigsimulator vliegt bijvoorbeeld niet echt. Een simulatie heeft dus betrekking op een model om het gedrag van een systeem te begrijpen, te voorspellen of te ontwerpen. Het creëert de mogelijkheden van het systeem niet opnieuw [3]. Een emulatie creëert daarentegen een surrogaat voor het systeem dat alle of een deel van de mogelijkheden van het originele systeem nabootst. Een voorbeeld van een open-source emulatieprogramma is Netkit. Het stelt gebruikers in staat om op een eenvoudige manier en aan een lage kostprijs een volledig netwerk te emuleren op één enkele pc. En hoewel alles virtueel is hebben de makers er toch voor gezorgd dat de kloof met de realiteit zo klein mogelijk is. Het virtueel netwerk zal op dezelfde manier geconfigureerd kunnen worden als een echt computernetwerk.
Inleiding Om een netwerk te emuleren met Netkit is het enkel nodig om een shellscript te schrijven en uit te voeren. Zo'n script start de virtuele pc's en routers1 op en verbindt ze zoals de gebruiker dat wenst. Een alternatieve manier om netwerkdemo's te maken voor Netkit is het gebruik van NetML. Dit is een op XML gebaseerde taal waarmee de gebruiker eenvoudige netwerkbeschrijvingen kan maken [4]. Deze beschrijvingen kunnen naast Netkitdemo's ook omgezet worden naar configuratiebestanden voor sommige routers. Netkit is voor het overgrote deel gebaseerd op User-Mode Linux. Voor dit eindwerk hebben we User-Mode Linux gebruikt als virtuele omgeving op ongeveer dezelfde manier als Netkit dat doet. We maken een shellscript dat een netwerkdemo start zoals bij Netkit, maar dan zonder gebruik te maken van Netkit zelf. Dit geeft ons meer vrijheid en meer inzicht in de exacte werking van de emulatie.
1.3 Doel van het eindwerk In dit eindwerk is het de bedoeling om netwerkdemo's te maken waarin de gebruiker op een veilige en vooral goedkope manier nieuwe systemen en protocols kan uittesten. Zowel de testomgeving als de protocols bestaan volledig uit open-sourcesoftware. De eerstvolgende twee hoofdstukken handelen over de testomgeving. User-Mode Linux is in staat om een volledig netwerk van virtuele Linux-pc's en routers aan te maken. Hiervoor is slechts één enkele pc met het besturingssysteem Linux nodig. Het virtuele netwerk zal dienen om alle programma's en protocols op uit te testen. De overgang van User-Mode Linux naar een echt netwerk is daarna nog slechts een kleine stap. Vervolgens komt in hoofdstuk 4 de visualisatie van het netwerkverkeer met behulp van RRDtool aan bod. RRDtool is een pakket dat databases aanmaakt voor de nodige gegevens. Het kan ook op een eenvoudige manier grafieken maken van alle gegevens in zijn databases. RRDtool krijgt de nodige gegevens van de router met behulp van SNMP. Verder handelt hoofdstuk 5 over Linux Traffic Control. Dit is een protocol dat het dataverkeer over een netwerk controleert en limiteert. En tot slot geeft hoofdstuk 6 nog wat meer uitleg over de verschillende scripts die het werk een stuk vergemakkelijken. Het werkt zowel het installatiescript als de verschillende opstartscripts verder uit.
1
Een router is een onderdeel van een computernetwerk dat datapakketten buffert en doorstuurt naar een bestemming binnen een privaat netwerk. Dit wordt ook routing genoemd en vindt plaats binnen de derde laag van het OSI-model, de netwerklaag. Zie hoofdstuk 3 voor uitleg over het OSI-model.
8
Hoofdstuk 2: User-Mode Linux User-Mode Linux laat toe verschillende virtuele Linuxsystemen (guests) te draaien als een applicatie binnen een bestaand Linuxsysteem (host). Iedere guest draait als een proces in de user space1. Doordat User-Mode Linux toelaat om verschillende Linuxsystemen te draaien op één enkele pc biedt het een uitstekende veiligheid en zekerheid naar de host toe op vlak van configuratie en stabiliteit. Hierdoor leent het zich uitstekend voor educatieve doeleinden en kan het ook dienen om nieuwe software te testen en te debuggen zonder de host te beïnvloeden.
Figuur 2.1: Vergelijking tussen UML en Qemu De schema's in figuur 2.1 schetsen de opbouw van twee virtuele systemen. Het linkse schema geeft User-Mode Linux schematisch weer. Hierin zien we dat een UML-kernel de belangrijke schakel is tussen de processen die in het virtuele systeem draaien en de Linuxkernel van de host. Het rechterschema toont duidelijk dat de virtualisatie hier voor een andere aanpak kiest. Een emulator zoals Qemu voorziet een extra laag virtuele hardware in de opstelling. Deze virtuele hardware zorgt voor de communicatie tussen de beide Linuxkernels. De kernel van het virtuele systeem is daarom een gewone Linuxkernel die niet speciaal voor de emulatie gecompileerd hoeft te worden.
2.1 Aanpassingen in het host-besturingssysteem Er bestaan twee verschillende modes waarin de host kan werken. De oude mode wordt tt-mode genoemd, wat voor Tracing Thread staat. User-Mode Linux draait in deze mode indien er vanuit de host geen ondersteuning voorzien is voor User-Mode Linux. Indien de host-kernel gepatched wordt dan kan User-Mode Linux in de nieuwe mode draaien. Deze mode wordt SKAS-mode genoemd. Dit staat voor Separate Kernel Address Space.
2.1.1 SKAS-patch Oorspronkelijk heeft een User-Mode Linux een specifieke opbouw. Elk proces van een UML komt overeen met een apart proces op de host. In Linux bestaat er een speciale thread2, de tracing thread. 1
De user space is het geheugengebied waarin alle gebruikerstoepassingen werken. Een thread is een proces dat binnen een ander proces uitgevoerd wordt. Met behulp van threads kan een computerprogramma verschillende taken tegelijkertijd uitvoeren. 2
9
User-Mode Linux Deze thread is noodzakelijk om system calls3 van alle processen te onderscheppen. Als een proces van een virtuele machine een system call uitvoert is deze gericht aan de kernel van de virtuele machine zelf. Deze verwijst de system call vervolgens door naar de kernel van het host-besturingssysteem. Het antwoord moet uiteindelijk weer via dezelfde weg terug. Dit houdt een serieuze performantiedaling in. Om dit tegen te gaan wordt er een nieuwe system call in de host-kernel voorzien die processen toelaat om hun eigen system calls te onderscheppen. De gelimiteerde ondersteuning voor User-Mode Linux in een gewone Linuxkernel veroorzaakt daarbuiten nog een aantal problemen. De UML-kernel is aanwezig in dezelfde adresruimte als alle processen van de host-pc en is bijgevolg van buiten af aanpasbaar. Deze schrijftoegang tot de kerneldata vormt een duidelijk veiligheidsprobleem. Dit kan veroorzaken dat de UML buiten zijn toegewezen geheugenbereik kan schrijven, wat je absoluut moet vermijden. De jail-mode verhelpt dit probleem door de UML-data readonly te maken terwijl een proces loopt. Dit veroorzaakt echter een extra performantiedaling. De SKAS-patch biedt een oplossing voor deze problemen. Een gepatchte Linuxkernel laat toe dat de UML's in de veiligere SKAS-mode opstarten. De aanpassingen die de SKAS-patch in de Linux-host aanbrengt verplichten de UML-kernel in een totaal ander adresgebied te lopen dan zijn eigen processen. Dit lost de problemen inzake veiligheid op. De adresgebieden in de guests zijn identiek aan wat ze zouden zijn op de host. De SKAS-mode vereist dat je een patch uitvoert op de broncode van de host-kernel alvorens je deze gaat compileren. De patch implementeert de ondersteuning voor aparte adresgebieden die nodig is voor SKAS-mode en nog enkele noodzakelijke toevoegingen aan ptrace4. Vooraleer je de kernel kan patchen moet je eerst nog extra software installeren in Ubuntu die dit mogelijk maakt. sudo apt-get install build-essential \ linux-source-2.6.17 \ kernel-package \ libncurses5-dev
Merk hierbij op dat de eerste regels van dit commando eindigen met een backslash. Dit wil zeggen dat het commando nog niet volledig is, maar dat er nog tekst volgt op een volgende regel. Normaal voer je een commando uit op één regel, maar om esthetische redenen kan je het soms beter splitsen in meerdere opeenvolgende regels. Als je dit commando in een script zou gebruiken, dan kan je het ook splitsen om het overzicht wat te bewaren. Vervolgens moet je de kernel uitpakken in de daarvoor voorziene map. cd /usr/src sudo tar xvfj linux-source-2.6.17.tar.bz2
Omdat Ubuntu 6.10 met een 2.6.17-kernel werkt moet je skas-2.6.17-rc5-v9-pre9.patch.bz2 downloaden van http://www.user-mode-linux.org/~blaisorblade/patches/skas3-2.6/. Deze plaats je zonder uit te pakken in de map /usr/src/. Vervolgens ga je naar de submap linux-source-2.6.17 en patch je de bronbestanden van de kernel met volgend commando. 3
Een system call is een mechanisme dat een computerprogramma gebruikt om een service van het besturingssysteem te verkrijgen. 4 Ptrace() is een system call die een proces toelaat om de uitvoering van een ander proces te controleren.
10
User-Mode Linux cd linux-source-2.6.17 bunzip2 -cd ../skas-2.6.17-rc5-v9-pre9.patch.bz2 | \ sudo patch -p1 --dry-run
De optie dry-run geeft aan dat het commando nog niks effectief verandert in de broncode. De patch test alleen of alles wel goed zal verlopen. Indien nergens in de output failed voorkomt is het veilig om deze patch daadwerkelijk toe te passen op de broncode van de kernel. Dit doe je door hetzelfde commando uit te voeren, maar dan zonder de optie dry-run. bunzip2 -cd ../skas-2.6.17-rc5-v9-pre9.patch.bz2 | sudo patch -p1
2.1.2 Kernel compileren Als je de kernel gepatched hebt moet je het configuratiebestand van de geïnstalleerde kernel kopiëren naar de map /usr/src/linux-source-2.6.17 en hernoemen naar .config. Deze nieuwe naam is nodig omdat het commando dat de kernel compileert de configuratie van de kernel automatisch uit het bestand .config leest. sudo cp /boot/config-2.6.17-10-generic .config
Wanneer je eventueel ook nog extra opties wilt toevoegen alvorens de kernel te compileren, dan kan dit eenvoudig door een configuratiemenu te starten en de opties aan te vinken. sudo make menuconfig
Voordat je de opties aanvinkt laad je best het .config-bestand door "Load an Alternate Configuration File" te selecteren in het configuratiemenu, zoals in figuur 2.2 te zien is. Aangezien Ubuntu gebaseerd is op Debian kan je gebruik maken van de Debian-tools om de kernel te compileren. Dit vergemakkelijkt de installatie een heel stuk. Je kan een .deb-bestand van de gecompileerde kernel maken dat je achteraf eenvoudig kan installeren. Hiervoor hoef je maar één keer te compileren en de installatie zal nu voor de rest geheel vanzelf gebeuren. De installatie door middel van een .deb-bestand zorgt ook zelf voor een entry in de bootloader. sudo make-kpkg --initrd \ --append-to=-project kernel_image kernel_headers
Als je de UML nu start zal hij de ondersteuning van de host proberen te detecteren. Indien dit niet lukt zal hij terugvallen op de oude tt-mode. Als de UML de SKAS-patch wel correct kan gebruiken, dan zal de host-kernel het aantal processen dat tot de UML behoort reduceren tot vier. Het eerste van deze vier processen is de UML-kernelthread die in het gescheiden kerneladresgebied loopt. Deze thread voert de kernelcode uit en onderschept de system calls van UML-processen. Een tweede belangrijk proces is de thread voor de user space van de UML. Deze voert alle UML-processen uit. Als derde proces treffen we de ubd-driverthread aan. Dit proces staat in voor het asynchroon I/O-gebeuren. Dit is alles wat met het dataverkeer van en naar een harde schijf te maken heeft. Het laatste proces is de SIGIO emulatiethread. SIGIO is een synoniem voor SIGPOLL, wat het signaal is dat programma's teruggeven wanneer een asynchrone I/O-gebeurtenis plaatsvindt. 11
User-Mode Linux
Figuur 2.2: Screenshot van een menuconfig
2.2 Guest-besturingssysteem Om de UML-guest te kunnen starten heb je een image en een UML-kernel nodig.
2.2.1 Image Als eerste heb je een image met een bestandssysteem nodig waarvan je je UML's kan starten. Een kant en klare image kan je afhalen van http://uml.nagafix.co.uk/, maar je kan ook zelf een image aanmaken. Op dit laatste gaan we hier niet dieper in, aangezien er voldoende images beschikbaar zijn. In bijlage B vind je meer info over hoe je een eigen image met een bestandsysteem kan aanmaken. De images voor UML's zijn allemaal zo klein en compact mogelijk gehouden. Een Linuxdistributie die zich goed leent voor kleine images is Debian Linux. Een ander voordeel van Debian is dat de pakketmanager, apt-get, toegang heeft tot een zeer groot aanbod aan pakketten. Als je dus een pakket nodig hebt in je UML, is de kans groot dat je ze met de pakketmanager snel en makkelijk kan afhalen. Starten van een image heeft echter ook enkele nadelen. Een imagebestand is veel gevoeliger voor fouten dan een normale partitie op een harde schijf. Als bij het wegschrijven naar een imagebestand een fout optreedt is de kans groot dat het bestand beschadigd is. Voor dit geval bestaan er tools om een image te herstellen, maar dit neemt vaak veel tijd in beslag en ze garanderen niet altijd een volledig herstel. 12
User-Mode Linux Om deze reden kan User-Mode Linux ook met een COW-bestand (Copy On Write) werken. Dit is een bestand dat je samen met de image meegeeft aan het opstartcommando voor een UML. User-Mode Linux schrijft nu alle aanpassingen weg in dit COW-bestand, zodat de originele image behouden blijft. Als er nu een schrijffout optreedt, of je richt zelf onherstelbare schade aan in je UML, dan is het voldoende om het COW-bestand te wissen. Nu kan je de UML opnieuw starten met de originele image en een nieuw COW-bestand. Doordat User-Mode Linux in een COW-bestand enkel de aanpassingen van het imagebestand wegschrijft, blijven deze bestanden relatief klein. Je hebt dus niet veel extra schrijfruimte nodig. Als je meerdere UML's tegelijk wilt starten spaar je zelfs schijfruimte uit als je met COW-bestanden werkt. Daar waar je anders voor elke UML een apart imagebestand nodig hebt, heb je nu slechts één image nodig. Voor elke UML gebruik je dan een apart COW-bestand, zodat elke UML toch verschillend kan zijn. Als je een imagebestand gebruikt in combinatie met een COW-bestand moet je er wel rekening mee houden dat User-Mode Linux bij het opstarten altijd kijkt naar de bestandsnaam en de tijd waarop het imagebestand het laatst is aangepast. Dit heeft als gevolg dat je een imagebestand niet zomaar mag kopiëren, want dan verandert de aanpassingstijd naar de tijd van kopiëren. Als je dus een back-up wilt maken van je imagebestand moet je dit doen op een manier waarbij de originele tijd behouden blijft, anders zal je COW-bestand niet meer overeenkomen met je imagebestand. In Linux kan je dit doen met het commando cp -p.
2.2.2 Kernel compileren De UML-kernel moet je zelf compileren. Zonder kernel kan je niet booten van je image. Alvorens je de kernel kan compileren moeten je er zeker van zijn dat je de benodigde software geïnstalleerd hebt. sudo apt-get install build-essential \ libncurses5-dev
Vervolgens download je een Linuxkernel van http://www.kernel.org en pak je deze uit in de home-map. tar -xvzf linux-2.6.20.1.tar.gz
Voor een .tar.gz-archief geef je best -xvzf mee als argumenten bij het tar-commando. De x wil hier zeggen dat je bestanden van een archief uitpakt. De v zorgt ervoor dat je een output op het scherm ziet. Zo kan je zien wat tar allemaal uitpakt en waar. De z moet je meegeven omdat het om een .gz-archief gaat. En de f tenslotte, duidt aan dat de bestandsnaam van het archief dat je uitpakt nog volgt. Als je de kernel hebt uitgepakt kan je de voorbereidingen beginnen om de Linuxkernel te compileren. Omdat je gaat compileren voor de speciale architectuur van User-Mode Linux geef je bij de commando's telkens de optie ARCH=um mee. cd linux-2.6.20.1 make mrproper ARCH=um make defconfig ARCH=um make menuconfig ARCH=um
Als eerste kuis je de kernelcode op. Het commando make mrproper wist de eventueel aanwezige configuratie of de objecten die zich in de map bevinden. Het kan nooit kwaad om dit commando uit te 13
User-Mode Linux voeren, ook niet als je nog nooit een kernel gecompileerd hebt. Met make defconfig vervolgens, laad je de standaardconfiguratie. Deze bevat de meest noodzakelijke opties die voor een kernel nodig zijn. Als je de optie ARCH=um meegeeft laad je automatisch de juiste standaardconfiguratie voor User-Mode Linux. Met een laatste commando voor je de kernel effectief kan gaan compileren open je het configuratiemenu. Er zijn enkele opties die je in het configuratiemenu zeker niet mag vergeten aan te passen. Ten eerste vink je Loadable module support best uit. Modules kunnen problemen veroorzaken in UML's. Alle andere opties die de kernel als module zou laden kan je dus ook best vast in de kernel compileren. Ten tweede moet je tunneling en 802.1d ethernet bridging aanvinken onder networking options. Als je dit niet doet zullen je UML's geen toegang hebben tot het internet. Tot slot kan je best alle opties die je niet nodig hebt, zoals bijvoorbeeld wireless LAN, uitvinken. Zo kan je de grootte van de kernel beperken, wat altijd een pluspunt is voor een UML-kernel [5]. Als de configuratie uiteindelijk voldoet aan alle eisen kan je overgaan tot de laatste stap, de kernel compileren. In het commando geef je een naam mee aan het bestand dat het commando gaat genereren, bijvoorbeeld linux. Met dit bestand kunnen we de image achteraf starten. make linux ARCH=um
2.2.3 UML's starten Nu je over zowel een image als een gecompileerde kernel beschikt, kan je een eerste UML opstarten. ./linux ubd0=mycow,Debian-root_fs 1 \ mem=64M 2 root=/dev/ubda 3 1
2
3
Met de eerste parameter geef je mee welk COW-bestand je gebruikt en van welke image je moet starten. Als het COW-bestand dat je opgeeft nog niet bestaat maakt User-Mode Linux dit zelf aan. Met deze parameter bepaal je hoeveel geheugen Linux moet reserveren voor deze UML. Meer geheugen resulteert in een snellere UML, maar je moet opletten dat je je UML's niet te veel geheugen geeft. Dat zou tot een instabiel systeem kunnen leiden. Deze derde parameter bepaalt waar de virtuele root van de UML zich bevindt.
Met dit commando kan je een eenvoudige UML opstarten, maar deze UML zal nog niet over netwerkmogelijkheden beschikken. Hoe je een netwerk van UML's kan maken legt hoofdstuk 3 in detail uit. Na hoofdstuk 3 kan je het commando om UML's te starten dan ook nog voor een stuk uitbreiden. De volledige commando's die we voor dit eindwerk gebruikt hebben om UML's te starten kan je terugvinden in hoofdstuk 6.
14
Hoofdstuk 3: Networking Voor User-Mode Linux zijn er verschillende manieren om de virtuele Linuxsystemen van een netwerkverbinding te voorzien. Deze netwerkverbinding kan dan dienen om een connectie te maken met de host-pc zelf, met andere systemen in het locale net of met het internet. Als we het netwerk aan de praat willen krijgen moet de guest-kernel dit wel ondersteunen.
3.1 Het OSI-model Het Open Systems Interconnection model is een abstracte beschrijving voor de communicatie binnen een netwerk en het ontwerp van protocollen in een computernetwerk. Het model bestaat uit zeven verschillende lagen die zich boven elkaar bevinden.
Figuur 3.1: Schema van het OSI-model De onderste laag van figuur 3.1 is de fysische laag. Deze beschrijft alle elektrische en fysische specificaties van desbetreffende apparaten. Het bevat de layout van de pinnen, connectoren, voltageniveau's en kabelspecificaties. De belangrijkste functies van de fysische laag bestaan eruit om een fysische connectie tussen de hardware en een communicatiemedium tot stand te brengen, in stand houden en indien nodig ook weer te deactiveren. Dit is het niveau waarop hubs1, repeaters2 en netwerkadapters werken. De tweede laag is de datalink- of verbindingslaag. Deze voorziet de functionaliteiten en procedures om data betrouwbaar te transporteren over een verbinding. Een eerste functionaliteit betreft het detecteren en eventueel corrigeren van fouten die kunnen optreden in de fysische laag. Een tweede functionaliteit 1
Een hub is een apparaatje dat voorzien is van een paar ethernetpoorten waar de netwerkkabels van meerdere computers samenkomen. De signalen die van een computer komen worden versterkt en doorgezonden naar alle andere kabels. 2 Een repeater is een elektronisch apparaat dat een zwak signaal ontvangt en het dan versterkt verder stuurt zodat het signaal langere afstanden kan overbruggen.
15
Networking bestaat uit het vastleggen van de adressen en de berichtformaten. Dit gebeurt op basis van het unieke, door de fabrikant toegekende MAC-adres3. Deze laag ordent de bits van de fysische laag tot stukken data, ook wel frames genoemd. Per frame bepaalt een aantal foutcontroles of het frame correct ontvangen is. Het meest bekende voorbeeld van deze laag is het ethernet. Laag drie vervolgens, staat ook wel bekend als de netwerklaag. Deze bevindt zich tussen de datalinklaag en de transportlaag. De netwerklaag is verantwoordelijk voor de overbrugging van de afstand tussen de omliggende lagen. Hij staat dus in voor het vertalen van een sessie in een verzameling pakketten die door de verschillende verbindingen in het netwerk geleid kunnen worden. Dit houdt in dat de laag een datastroom binnen een sessie in verschillende pakketten gaat opbreken. Hiernaast is deze laag ook verantwoordelijk voor de routing van de pakketten door het netwerk. Dit wil zeggen dat hij beslist hoe hij elk pakket over het netwerk zal versturen. De vierde laag uit figuur 3.1 is de laatste laag die instaat voor het datatransport. Deze laag, de transportlaag, zorgt voor een probleemloos transport van data voor de applicaties. De meest gebruikte protocollen uit deze laag zijn het Transmission Control Protocol (TCP) en het User Datagram Protocol (UDP). De eenheden van data uit deze laag worden meestal segmenten of datagrammen genoemd. De vijfde laag van het model wordt ook wel de sessielaag genoemd. Hij synchroniseert de dialoog die plaatsvindt op de presentatielaag tussen twee hosts en onderhoudt de uitwisseling van data. Problemen die zich voordoen binnen de toepassingslaag en de presentatielaag worden hier gemeld. De sessielaag biedt o.a. Class of Service (CoS). De voorlaatste laag is de presentatielaag. Deze bepaalt het uiteindelijk toegepaste formaat om data uit te wisselen. Bij de zendende computer vertaalt deze laag de data die door de toepassingslaag worden aangeboden in een gemeenschappelijk erkend tussenformaat. Bij de ontvangende computer vertaalt de presentatielaag het tussenformaat in een formaat dat de applicatielaag van die computer ondersteunt. De presentatielaag is ook verantwoordelijk voor protocolconversie. De protocolconversie vertaalt en codeert eventueel de data. Ook de tekenset wijzigen of converteren en grafische commando's uitbreiden zijn taken van de presentatielaag. Tevens houdt hij zich bezig met de compressie van data waardoor het aantal te verzenden bits vermindert. De bovenste van de drie lagen die in verbinding staan met de applicatie is de toepassingslaag. Deze communiceert direct met de betreffende applicatie en geeft opdrachten aan de presentatielaag. De laag staat ook het dichtst bij de gebruiker. E-mail, het HyperText Transfer Protocol (HTTP) en het File Transfer Protocol (FTP) communiceren op deze laag. De toepassingslaag onderscheidt zich van de andere lagen uit het OSI-model doordat het geen diensten aanbiedt aan de andere lagen, maar alleen naar de applicatie buiten het OSI-model.
3.2 Bridging Een eerste belangrijke techniek bij networking is bridging. Dit is een techniek om pakketten door te sturen van het ene naar het andere computernetwerk. Het maakt geen veronderstellingen over waar in een netwerk een bepaald adres aanwezig is. Deze techniek hangt af van broadcasting4 om een onbekend apparaat op te sporen. Vanaf het moment dat een apparaat opgespoord is wordt z'n locatie opgeslagen in een routingtabel. Deze tabel houdt het MAC-adres en het overeenstemmende IP-adres bij, zodat in de toekomst voor dit apparaat geen broadcast meer nodig is. 3
Het MAC-adres is een uniek identificatienummer dat aan een apparaat is toegekend. MAC staat voor Media Access Control. Een MAC-adres bestaat uit zes hexadecimale getallen. vb: 00:0C:6E:D2:11:E6 4 Een broadcast is een pakket dat elk ander apparaat in het netwerk kan ontvangen.
16
Networking De afhankelijkheid van broadcasting beperkt het gebruik van bridging. Hierdoor wordt het alleen maar gebruikt in Local Area Networks (LAN). Bridging laat toe om twee verschillende netwerken te verbinden op niveau van de datalinklaag. Qua werking gelijken een bridge en een switch heel erg op elkaar op een enkele uitzondering na. Een bridge is een apparaat dat tussen netwerken staat en het broadcastverkeer tussen de netwerken van elkaar scheidt. Een switch laat broadcasts gewoon passeren. In ons project maken we gebruik van dit principe om internettoegang te voorzien aan de virtuele systemen. Dit gebeurt echter niet op het hardwareniveau zoals hierboven beschreven, maar op een softwarematig niveau. Linux voorziet hier meestal standaard ondersteuning voor. In Ubuntu moet je hiervoor nog enkele pakketten installeren. sudo apt-get install bridge-utils \ uml-utilities 2 1 2
1
Dit pakket bevat de benodigdheden om de Linux ethernet bridge te configureren. Dit pakket bevat extra benodigdheden in de gebruikersomgeving voor User-Mode Linux.
Wij gebruiken een shellscript om deze software-bridge te starten. Omdat het nuttig is dit te starten bij het booten van de host hebben wij geopteerd deze te laten uitvoeren op het einde van het bootproces [6]. sudo sudo sudo sudo sudo sudo sudo sudo sudo 1 2
3 4 5
6
7 8 9
bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward' 1 ifconfig eth0 0.0.0.0 promisc up 2 brctl addbr uml-bridge 3 brctl setfd uml-bridge 0 4 brctl sethello uml-bridge 0 5 brctl stp uml-bridge off 6 ifconfig uml-bridge 10.1.202.84 netmask 255.255.255.0 up ip route add default via 10.1.202.1 8 brctl addif uml-bridge eth0 9
7
Dit commando activeert ip-forwarding dat de pakketten van de host verder kan sturen. Dit commando reset de ethernetpoort van de host naar een tijdelijke IP-vrije status. Alle netwerkactiviteiten zullen tijdelijk stilliggen. Dit commando voegt een nieuwe virtuele bridge toe met de naam uml-bridge. Dit commando bepaalt de vertraging bij het doorsturen van pakketten. Dit commando geeft op wat de hello-tijd is. Op het moment dat je een router opstart begint hij hello-pakketten te versturen in het netwerk om te melden dat hij nieuw is in het netwerk en om ervoor te zorgen dat andere routers hem leren kennen. Dit commando zet Spanning Tree Protocol (STP) af. STP is een protocol van de tweede laag in het OSI-model dat ervoor zorgt dat er geen lussen voorkomen in het netwerk. Dit commando geeft het IP-adres van de host aan de bridge. Het activeert tevens de bridge. Een voorlaatste commando voegt een default gateway toe. Dit laatste commando hangt de bridge aan de ethernetpoort.
Zie hoofdstuk 6 voor meer uitleg over het script waarin deze commando's voorkomen.
3.3 Tunneling Een volgende belangrijke techniek is tunneling. Dit is een netwerkprotocol dat een ander protocol of een sessie inkapselt in een protocol van een hogere of dezelfde laag. Het zou gebruikt kunnen worden om datalinklaagprotocol te transporteren via een transportlaagprotocol. 17
Networking
3.4 IP-maskerade Een laatste belangrijke techniek is IP-maskerade. Dit is een voorziening in de Linuxkernel die toelaat om pakketten te manipuleren zodat het lijkt alsof ze van andere adressen afkomstig zijn dan van de originele bron. Deze maskerade van de pakketten gebeurt alleen tijdens het forwarden van pakketten. Maskerade van pakketten gebeurt in twee richtingen op een router. Een systeem dat zich in een privaat netwerk bevindt dat door een router gescheiden wordt van de buitenwereld kan communiceren met het internet via deze router. Als dit systeem een datapakket naar het internet wil versturen moet dit altijd door de router passeren. Als het pakketje aankomt in de router kijkt hij waar dit pakketje naartoe moet. Alleen als de bestemming buiten het private netwerk ligt stuurt hij het pakketje door naar de buitenwereld. Voordat de router het pakket daadwerkelijk verstuurt verandert hij het IP-adres van de zender in het IP-adres van de router zelf. Zo denkt de buitenwereld dat het pakketje van de router afkomstig is. Een antwoord zal nu ook terug aankomen op de router. Als dit pakketje terugkomt weet de router dat hij dat verstuurd heeft en met wie hij z'n IP-adres gewisseld heeft. De router herstelt het originele IP-adres en stuurt het pakketje het private netwerk in. Hierdoor zal het uiteindelijk aankomen op het systeem dat het daadwerkelijk verstuurd heeft. Maskerade is noodzakelijk naar de buitenwereld toe omdat de buitenwereld de IP-adressen van de systemen in het private netwerk niet kent.
3.5 Testopstelling Om een veel voorkomende situatie te simuleren hebben we geopteerd voor een netwerk met een router en een eenvoudig achterliggend privaat netwerk, zoals figuur 3.2 aantoont.
Figuur 3.2: Schema van het virtuele netwerk Het is de bedoeling dat de router naast de host-pc aan de bridge hangt. Hiervoor maakt User-Mode Linux gebruik van het tunnelingsprincipe. De router heeft meerdere virtuele ethernetpoorten. De basispoort, eth0, is met de bridge verbonden via een tunnel. Het overige aantal poorten van de router zal 18
Networking dienen voor een overeenstemmend aantal private netwerken. In deze private netwerken zal User-Mode Linux een aantal andere systemen emuleren die met opzet zeer eenvoudig worden gehouden. Een switch5 verbindt de UML's van een bepaald subnetwerk met de overeenstemmende poort van de router. Een script start deze switch samen met de router. De switch is gewoon een proces dat enkel virtueel bestaat, net als de rest van het netwerk.
5
Een switch is een onderdeel van een computernetwerk dat lijkt op een bridge. Het enige verschil is dat een switch de binnenkomende pakketten niet filtert, maar gewoon allemaal doorstuurt naar de rest van het netwerk.
19
Hoofdstuk 4: Visualisatie De vorige twee hoofdstukken maakten duidelijk hoe je met User-Mode Linux op één enkele pc een volledig computernetwerk kan emuleren. Nu het volledige netwerk klaar is kan je beginnen met het uittesten van verschillende protocols. Dit hoofdstuk legt uit hoe je gegevens over je netwerk kan opvragen, in een database opslaan en grafisch weergeven. De oplossing zal weer enkel uit open-sourcesoftware bestaan. Dit hoofdstuk gaat uit van een netwerk met een router waarop twee guest-UML's hangen. De router is via eth0 met het internet en via eth1 en eth2 met respectievelijk UML1-1 en UML2-1 verbonden. Een grafische weergave van het gebruikte netwerk kan je zien in figuur 4.1.
Figuur 4.1: Schematische voorstelling van het voorbeeldnetwerk
4.1 SNMP Simple Network Management Protocol is een protocol dat over een TCP/IP-netwerk werkt om informatie van systemen die op het netwerk zijn aangesloten op te vragen. Het kan bijvoorbeeld op een eenvoudige manier de status van een harde schijf van een server opvragen of de hoeveelheid dataverkeer dat er over een netwerk gaat. Deze informatie kan dan door andere tools verder verwerkt worden. SNMP vereist nagenoeg geen bandbreedte en dat maakt het protocol erg geliefd om bepaalde toepassingen van op afstand aan te sturen. Grotere bedrijven gebruiken het protocol ook om een volledig netwerk te routeren langs de interne servers. Op deze manier kan het netwerk op de meest efficiënte wijze worden gebruikt [7].
4.1.1 Management Information Base SNMP werkt met Management Information Bases of MIBs om al zijn informatie bij te houden. Een MIB is een verzameling informatie die hiërarchisch wordt opgeslagen. Door de hiërarchie is het makkelijk om een bepaalde waarde op te vragen. Hiervoor moet je wel de plaats van de informatie in de gehele structuur weten. Zie figuur 4.2 voor een voorbeeld van de structuur van een MIB zoals die van SNMP. Een element in een MIB wordt een MIB-object genoemd. Vaak zal echter ook gewoon met de term MIB naar een MIB-object worden verwezen. Dit kan voor enige verwarring zorgen. Een MIB-object kan op twee manieren worden weergegeven. Zowel een weergave met getallen als een weergave met woorden kunnen worden gebruikt. In figuur 4.2 kan je zien dat 1.3.6.1.2.1.2 20
Visualisatie en iso.org.dod.internet.mgmt.mib-2 beiden naar hetzelfde object verwijzen. De eerste weergave lijkt misschien handiger, maar voor wie meer ervaring heeft met MIB's biedt de tweede weergave een veel snellere werkwijze.
Figuur 4.2: Hiërarchische structuur van een MIB
4.1.2 Structuur SNMP bestaat uit drie onderdelen [8]. Een eerste onderdeel is de master-agent. Dit is een programma dat op een component van het netwerk draait en waarvan je informatie kan opvragen. Een master-agent draait meestal op een router of een server. Een tweede onderdeel is de subagent. Dit is een onderdeel dat data gaat genereren in een vorm die compatibel is met overeenstemmende MIB. Een master-agent heeft subagents nodig om data te verkrijgen. Voor verschillende soorten data heeft een master-agent ook meerdere verschillende subagents nodig. Het derde en laatste onderdeel is het management station of de manager. Dit onderdeel kan data opvragen bij een master-agent door middel van het juiste commando. Een manager kan op om het even welke component uit het netwerk geïnstalleerd zijn. Vaak zal dit een server of pc zijn die de data verder verwerkt of grafisch weergeeft. Het is ook mogelijk om meerdere onderdelen te combineren. Zo kan bijvoorbeeld een server als master-agent en als management station fungeren. In dit geval zou de server eigen data opvragen en zelf verwerken tot de gewenste output. 21
Visualisatie
4.1.3 Praktische informatie Naast de gewone SNMP zijn ook al vervolgversies uitgebracht. SNMPv2 en SNMPv3 staan een intelligenter systeem toe dan SNMPv1. Deze nieuwe standaarden zijn meer uitgebreid en veiliger dan het origineel. Ze zouden als basis moeten gaan dienen voor alle nieuwe high-end LAN, WAN en mobiele systemen. Veel fabrikanten bouwen daarom nu al apparatuur waarin een nieuw protocol als standaard is opgenomen [7]. Voor dit werk hebben we gewoon SNMPv1 gebruikt. Om makkelijk met SNMP te werken kan je hiervoor kant-en-klare softwarepakketten afhalen. Deze maken het makkelijker om met SNMP en MIB's te werken. Ze bevatten vaak vele handige hulpmiddelen. Een voorbeeld van zo'n pakket is net-snmp. Voor meer info over dit pakket kan je terecht op http://net-snmp.sourceforge.net/. Hier kan je net-snmp ook downloaden. Een belangrijk commando voor SNMP is snmpwalk. Hiermee vraag je een hele boel informatie op uit de MIB. Dit is vooral handig als je niet exact weet welk MIB-object je juist nodig hebt voor de informatie die je zoekt. Als we bijvoorbeeld willen nagaan welke netwerkpoorten (interfaces) er allemaal zijn, vragen we alle informatie van interfaces.ifTable.ifEntry.ifDescr op. Dit doen we met volgend commando [9]: snmpwalk -v1 -c gf 127.0.0.1 interfaces.ifTable.ifEntry.ifDescr
Achter snmpwalk geef je als eerste mee welke versie je gebruikt. Als je SNMPv1 gebruikt is dit niet noodzakelijk, maar voor de duidelijkheid doe je dit best toch. Vervolgens geef je met -c de naam van de community mee. Enkel wie de juiste community kent, kan data opvragen met SNMPv1. Als voorlaatste geef je het IP-adres van het doel op. Als de master-agent en de manager op hetzelfde systeem geïnstalleerd zijn moet je het loopback-adres1 meegeven. Tot slot geef je nog de MIB mee waarvan je alle subparameters wilt weergeven. Een snmpwalk, zoals hierboven, resulteert in ons voorbeeldnetwerk in volgende output: IF-MIB::ifDescr.1 IF-MIB::ifDescr.2 IF-MIB::ifDescr.3 IF-MIB::ifDescr.4 IF-MIB::ifDescr.5 IF-MIB::ifDescr.6
= = = = = =
STRING: STRING: STRING: STRING: STRING: STRING:
lo dummy0 tunl0 eth1 eth2 eth0
Hieruit kunnen we afleiden welke poorten er allemaal door SNMP gecontroleerd worden. Ook zien we op welke plaats in de MIB ze zich bevinden. Eén enkele waarde uit de MIB halen doen we met het commando snmpget. Als we bijvoorbeeld van eth1 het inkomende en uitgaande dataverkeer willen opvragen, doen we dit met de volgende twee commando's: snmpget -v1 -c gf 127.0.0.1 interfaces.ifTable.ifEntry.ifInOctets.4 snmpget -v1 -c gf 127.0.0.1 interfaces.ifTable.ifEntry.ifOutOctets.4
Hier hebben de eerste parameters achter snmpget weer dezelfde betekenis als hierboven bij snmpwalk. Als laatste parameter geef je het gevraagde MIB-object mee. Voor het inkomend verkeer op eth0, bijvoorbeeld, zou dit interfaces.ifTable.ifEntry.ifInOctets.6 zijn. 1
Het loopback-adres, 127.0.0.1 of localhost, is een IP-adres dat terug naar het eigen systeem verwijst. Pakketten die naar het loopback-adres gestuurd worden komen nooit echt op het netwerk terecht en veroorzaken dus ook geen netwerkverkeer.
22
Visualisatie
4.2 RRDtool Als je de nodige data opgevraagd hebt met een manager moet je de data opslaan om ze dan uiteindelijk weer te geven op een overzichtelijke manier, bijvoorbeeld een grafiek. Zowel het opslaan van data in een database als het genereren van grafieken uit deze databases kan je met één en hetzelfde pakket doen. RRDtool biedt de mogelijkheid om een eigen database te maken en de inhoud in grafieken weer te geven die je tot in de kleinste details kan aanpassen. RRDtool, oftewel Round Robin Database tool, is open-sourcesoftware, gecreëerd door Tobias Oetiker. Doordat het ook grafieken kan maken is het meer dan een gewone database-tool. RRDtool heeft nog enkele andere verschillen met andere databasetools [10]. De meeste andere databases zijn lineair. Dat wil zeggen dat nieuwe data automatisch achteraan de database worden toegevoegd. De grootte van de database blijft dus groeien naargelang de tijd dat je data opslaat langer wordt. RRDtool maakt gebruik van round robin databases. De grootte van deze databases wordt vastgelegd bij het aanmaken en zal altijd behouden blijven. De databases werken volgens een circulair principe (vandaar round robin), waarbij voor elke nieuwe waarde één plaats wordt opgeschoven op de cirkel. Als de cirkel vol staat zal vanzelf de eerste waarde overschreven worden, zodat je nooit onnodig veel data zal bekomen. Je moet er natuurlijk wel voor zorgen dat je je database van in het begin groot genoeg maakt voor je toepassing. Een schema van een circulaire database kan je zien in figuur 4.3.
Figuur 4.3: Schematische weergave van een eenvoudige circulaire database Een ander verschil is dat RRDtool veel meer doet dan gewoon aangeboden data opslaan in een database. Het kan berekeningen uitvoeren alvorens de waardes op te slaan. Zo kan je bijvoorbeeld het verschil tussen twee opeenvolgende waardes opslaan, in plaats van de waardes zelf. Hiervoor hoef je geen beroep te doen op een extern programma om de berekeningen te doen, wat bij de meeste andere databases wel het geval is. Een laatste verschil is dat de meeste databasepakketten hun databases updaten zodra er nieuwe data beschikbaar is. RRDtool update zijn database altijd op een vast tijdsinterval. Je moet dus zorgen dat je de data ook op een vast tijdsinterval aan RRDtool aanbiedt. Als er niet op tijd data beschikbaar zijn slaat RRDtool een unknown op in de database. Het is dus belangrijk dat je een script gebruikt dat 23
Visualisatie data op een vast tijdsinterval opvraagt en doorgeeft aan RRDtool. Als het tijdsinterval toch niet perfect constant is, kan RRDtool een goede benadering van de juiste waardes bekomen door te interpoleren tussen meerdere waardes.
4.2.1 Database Een database aanmaken Zoals eerder reeds vermeld is, gebruikt RRDtool round robin databases om zijn data op te slaan. Een voorbeeld maakt de opbouw en structuur van zo'n database duidelijk [10]. De database wordt aangemaakt met volgend commando: rrdtool create eth0.rrd 1 \ --start 487789200 2 --step 60 3 \ DS:input:COUNTER:120:U:U \ 4 DS:output:COUNTER:120:U:U \ RRA:AVERAGE:0.5:1:300 \ 5 RRA:AVERAGE:0.5:5:600 \ RRA:AVERAGE:0.5:30:600 \ RRA:AVERAGE:0.5:120:600 \ RRA:AVERAGE:0.5:1440:400 1
2 3
4
5
Hier geef je de naam van de database op en eventueel ook het pad naar de locatie waar je de database wilt opslaan. Hiermee stel je de starttijd van een database in. Deze parameter geeft de stapgrootte tussen twee waardes in de database mee. Je moet proberen om nieuwe waardes op dit interval aan de database mee te geven. DS staat voor Data Source. Hiermee worden de variabelen aangemaakt van de parameters die RRDtool moet opslaan en weergeven. RRA's zijn Round Robin Archives. In deze archieven slaat RRDtool zijn data effectief op.
Als start- en eindtijd moet je een tijd opgeven in seconden sinds epoch. Epoch wordt in de computerwereld als het begin van de tijdsrekening genomen. Dit komt overeen met 1 januari 1970, om één seconde na middernacht GMT. Het is echter ook mogelijk om een relatieve tijd mee te geven ten opzichte van de huidige tijd. Dit doe je door een negatieve waarde mee te geven. Als je de starttijd niet meegeeft neemt RRDtool de standaardtijd, namelijk exact één dag voor de huidige tijd. Als je geen eindtijd meegeeft neemt RRDtool de huidige tijd als eindtijd. Bij de data source moet je enkele opties meegeven. Achter de eerste dubbelpunt staat de naam van de variabele. Vervolgens komt het Data Source Type, of DST. Hiermee bepaal je welk type variabele je opslaat. Een DST kan één van de volgende waardes aannemen: COUNTER, DERIVE, ABSOLUTE en GAUGE [10]. Voor een DS van gegevens over netwerkverkeer is COUNTER het meest geschikte DST. Vervolgens moet je een hartbeat voor je reeks data opgeven. Dit is de maximale tijd die RRDtool mag wachten op een nieuwe waarde. Als de database geen nieuwe waarde krijgt binnen de heartbeat zal hij een unknown opslaan. De laatste twee waardes zijn respectievelijk de maximale en de minimale waarde van de data. Als er geen maximale en minimale waarde bestaat of als deze niet gekend zijn, kan je hier ook 'U' opgeven. Een RRA bevat de data die RRDtool gebruikt om grafieken uit te genereren. Als eerste parameter achter RRA geef je de consolidation function of CF van het archief mee. Als je het gemiddelde van de 24
Visualisatie waarden binnen het tijdsinterval wilt opslaan neem je AVERAGE als CF. Wil je de maximale waarde bijhouden, dan neem je MAXIMUM als CF. Je kan ook twee verschillende RRA's maken, waarbij je in de eerste het gemiddelde bijhoudt en in de tweede het maximum. Andere mogelijkheden voor CF zijn MINIMUM en LAST [11]. Vervolgens geef je de X-Files Factor of xff op. Deze factor is het percentage van waardes dat unknown mag zijn voordat het resultaat van de berekening ook unknown wordt. Als voorlaatste parameter geef je het aantal stappen mee waaruit de waarde in het RRA moet worden berekend. En tot slot moet je nog meegeven uit hoeveel waardes of rijen het RRA moet bestaan. Om de vorige paragrafen wat te verduidelijken gaan we het archief RRA:AVERAGE:0.5:5:600 eens in detail bekijken. De CF is AVERAGE. Dit RRA zal dus een gemiddelde waarde bijhouden van beide data sources in het voorbeeld. Het aantal stappen van dit RRA is 5. Dit wil zeggen dat er 5 stappen moeten worden samengenomen, alvorens RRDtool het gemiddelde berekent. Aangezien de stapgrootte van de database 60 seconden is, zal dit RRA uit rijen van 5 * 60 seconden of 5 minuten bestaan. Dit RRA moet 600 rijen bijhouden, wat goed is voor 600 * 5 minuten of 50 uur aan data. Een schematisch overzicht van alle RRA's in ons voorbeeld kan je zien op figuur 4.4. Merk op dat deze structuur van RRA's voor elke DS wordt aangemaakt. Hier wordt dus van elke RRA één voor het inkomend en één voor het uitgaand verkeer aangemaakt.
Figuur 4.4: Schematische weergave van de RRDtool-database 25
Visualisatie
Een database updaten Van zodra je een database hebt aangemaakt kan je beginnen met gegevens invoeren. Dit doe je door het update-commando op een regelmatig tijdstip uit te voeren. Om dit laatste wat te vergemakkelijken maak je best gebruik van een script dat de juiste timing voor zijn rekening neemt. Meer info over een mogelijk script kan je vinden in hoofdstuk 6. Het commando om een database te updaten ziet er als volgt uit: rrdtool update 1 eth0.rrd 2 N:$in:$out 3 1
2
3
De update kan je ook vervangen door updatev. Dit heeft hetzelfde resultaat als een gewone update, maar RRDtool print nu alle acties die hij onderneemt naar het scherm, zodat je makkelijk alle stappen kan controleren. Hier geef je de naam van de database op die je gaat updaten met eventueel een pad naar de juiste locatie. Met deze laatste parameters geef je de tijd en de waardes mee. De eerste van deze parameters is de tijd waarvoor de waardes geldig zijn. Je moet de tijd weer in seconden sinds epoch opgeven, zoals hierboven is uitgelegd. Als je de waardes opvraagt en rechtstreeks aan de database toevoegt kan je hier ook N opgeven. Dit staat voor de huidige tijd. Achter het eerste dubbelpunt volgen de waardes die je voor dat tijdstip meegeeft, elk van de vorige gescheiden door een nieuwe dubbelpunt. In ons voorbeeld zijn dit voor elk tijdstip twee waardes, namelijk het inkomend en het uitgaand verkeer.
4.2.2 Grafieken Nadat je een database aangemaakt en gevuld hebt wil je de opgeslagen waardes uiteraard grafisch weergeven. Hiervoor is geen externe software nodig. RRDtool beschikt over een commando dat snel en makkelijk grafieken kan genereren uit een van zijn databases. Je kan door middel van enkele parameters de bekomen grafiek tot in de details aanpassen. Een grafiek genereren doe je met volgend commando: rrdtool graph grafieken/eth0.png 1 \ --start -3600 2 -t eth0 3 -z 4 \ "DEF:inoctets=eth0.rrd:input:AVERAGE" \ 5 "DEF:outoctets=eth0.rrd:output:AVERAGE" \ AREA:inoctets#00FF00:"Inkomend verkeer" \ LINE1:outoctets#FF0000:"Uitgaand verkeer" 1
2
3
4
6 7
Met deze eerste parameter geef je de naam van de grafiek die je wilt genereren op. Als RRDtool de grafiek niet in de huidige map moet maken, kan je ook een pad opgeven naar de juiste locatie. RRDtool ondersteunt verschillende bestandstypen voor zijn grafieken, waaronder PNG en SVG. De starttijd van de grafieken moet je weer in seconden sinds epoch opgeven. Als je hier een negatieve waarde opgeeft resulteert dit in een relatieve tijd ten opzichte van de huidige tijd. De -3600 wil dus zeggen dat de grafiek 1 uur voor de huidige tijd moet beginnen. Als je geen starttijd opgeeft neemt RRDtool de tijd van exact één dag geleden als starttijd. Je kan op gelijkaardige manier met --end ook een eindtijd opgeven. Als je dit niet doet neemt RRDtool automatisch de huidige tijd als eindtijd [12]. Met deze parameter geef je een titel aan je grafiek. Als de titel langer is dan één woord moet je hem tussen dubbele aanhalingstekens zetten. De optie -z duidt aan dat RRDtool een grafiek enkel vernieuwt als er ook effectief veranderingen zijn ten opzichte van de vorige keer je deze grafiek genereerde. Als je bijvoorbeeld twee keer na 26
Visualisatie
5
6
7
elkaar dezelfde grafiek uit dezelfde database genereert is het niet altijd nodig om deze grafiek nog eens opnieuw aan te maken. De data zijn niet altijd voldoende veranderd om ook een verandering in de grafiek teweeg te brengen. In zo'n geval is het ook niet nodig om een nieuwe grafiek aan te maken. Een DEF is een definitie van een variabele. Deze regel zal data uit de database opvragen. Achter de eerste dubbelpunt kan je een naam opgeven waarmee je deze variabele verder in het commando kan oproepen. Na het gelijkheidsteken geef je de naam van de database mee waaruit je gegevens wilt ophalen. Als voorlaatste parameter geef je de naam van de DS mee die overeenkomt met de data die je wil weergeven. Als laatste geef je tenslotte nog de CF van de DS mee. Een area is een vol gebied in een grafiek. Achter de eerste dubbelpunt geef je de naam van de DEF die je wil weergeven mee, gevolgd door een hekje en een kleurcode. De kleurcode moet je meegeven in hexadecimaal formaat, zoals bij HTML ook het geval is. Vervolgens kan je nog een naam opgeven die in de legende te zien is. In figuur 4.5 tot en met figuur 4.8 kan je een groen gebied zien, zoals dit voorbeeldcommando zou genereren. Naast een vol gebied kan je ook lijnen tekenen in een grafiek. Je kan zowel line1, line2 als line3 gebruiken voor respectievelijk een dunne, matige of dikke lijn. De opties bij een lijn zijn dezelfde als bij een vol gebied. In figuur 4.5 tot en met figuur 4.8 zie je een dunne lijn (line1), zoals het voorbeeldcommando zou genereren.
Merk op dat dit voorbeeld grafieken genereert in het PNG-formaat. Voor sommige toepassingen is een vectorieel formaat als SVG2 echter handiger. In zo'n geval geef je een bestandsnaam met de extensie .svg op. Om aan RRDtool duidelijk te maken dat je met een vectorieel formaat werkt, moet je ook de optie -a SVG aan het commando meegeven. De grafieken in figuur 4.5, figuur 4.6, figuur 4.7 en figuur 4.8 zijn vier grafieken uit één en dezelfde database. Deze database hebben we gevuld met willekeurige data om aan te tonen hoe je eenvoudig meerdere verschillende grafieken kan genereren uit dezelfde database. De vier grafieken hebben telkens een ander bereik en een andere resolutie. Om een goed overzicht te hebben over de verschillende grafieken kan je ze allemaal weergeven in een HTML-bestand. Als je dan nog een webserver, zoals Apache, opzet is het mogelijk om dit bestand van overal in het netwerk te bekijken. Je kan dus van op elke pc in het netwerk eenvoudig alle informatie over het netwerkverkeer opvragen, zonder dat je hiervoor speciale software moet installeren op deze pc. Een simpele webbrowser volstaat.
eth0: 2 uur 300 k
200 k
100 k
20:00
20:20
Inkomend verkeer
20:40
21:00
21:20
21:40
22:00
Uitgaand verkeer
Figuur 4.5: Voorbeeldgrafiek met 2 uren aan data 2
Scalable Vector Graphics: een taal die tweedimensionale figuren vectorieel beschrijft in XML [13].
27
Visualisatie
eth0: 24 uur 250 k 200 k 150 k 100 k 50 k
00:00
06:00
Inkomend verkeer
12:00
18:00
Uitgaand verkeer
Figuur 4.6: Voorbeeldgrafiek met 24 uren aan data eth0: 7 dagen 300 k
200 k
100 k
0 Wed
Inkomend verkeer
Fri
Sun
Uitgaand verkeer
Figuur 4.7: Voorbeeldgrafiek met 7 dagen aan data eth0: 30 dagen 300 k
200 k
100 k
0 Week 20
Inkomend verkeer
Week 21
Week 22
Week 23
Uitgaand verkeer
Figuur 4.8: Voorbeeldgrafiek met 30 dagen aan data Meer info over de verschillende commando's van RRDtool kan je online vinden op de website van Tobias Oetiker, http://oss.oetiker.ch/. Als je doorklikt naar Documentation kan je de originele Engelstalige documentatie van alle commando's bekijken.
28
Hoofdstuk 5: Traffic Control Traffic Control, vaak ook Traffic Shaping of Quality of Service (QoS) genoemd, is een vrij uitgebreid begrip. In het algemeen is het de bedoeling om zowel de vertraging als de doorvoersnelheid1 van data over een netwerk te regelen [14]. Standaard laat een router alle data door met eenzelfde prioriteit. Hij maakt dus geen onderscheid tussen verschillende soorten data. Hierbij kunnen echter problemen optreden. Denk bijvoorbeeld aan een website die zeer traag laadt als je op de achtergrond een bestand aan het downloaden bent met FTP. Het is dus gewenst dat bepaalde datastromen een gegarandeerde snelheid krijgen of dat de router ze een hogere prioriteit geeft dan de rest van het dataverkeer. Om dit te bereiken werkt de tc-tool met queuing disciplines of qdiscs. Een veelgebruikte qdisc die verschillende datastromen onafhankelijk behandelt is Hierarchical Token Bucket (HTB). Dit is een beter te begrijpen en snellere vervanging voor Class Based Queueing (CBQ) dat vooral vroeger in Linux gebruikt werd.
5.1 Hierarchical Token Bucket Zoals eerder reeds vermeld, werkt HTB volgens het principe van een queuing discipline (qdisc). Een qdisc kan je vergelijken met een pipe waar al het dataverkeer door moet. Een qdisc gedraagt zich als een FIFO2. Met behulp van de tc-tool en HTB kan je de grootte van deze FIFO bepalen, als ook de snelheid waarmee data uit de FIFO kunnen worden gehaald. Je kan ook meerdere FIFO's maken voor verschillende types van data. HTB maakt gebruik van klassen om de bandbreedte over een netwerkverbinding te controleren. Met klassen kan je de bandbreedte indelen in verschillende onderdelen. Deze onderdelen hebben niks te maken met de fysische eigenschappen van de verbinding, maar bestaan enkel virtueel. Met behulp van een filter kan je een bepaalde datastroom toekennen aan een klasse. Op deze manier verwerkt tc alle data die voldoen aan de vereisten van de filter zoals je hebt opgegeven in de overeenstemmende klasse. Zo kan je bijvoorbeeld een aparte klasse en filter maken voor al het HTTP-verkeer, of voor al het verkeer dat van een bepaald IP-adres afkomstig is.
Figuur 5.1: Schematische voorstelling van het voorbeeldnetwerk 1
De doorvoersnelheid of throughput is de snelheid waarmee de netwerkpoort de data verwerkt. First In, First Out: De pakketten die eerst toekomen in de FIFO worden er aan de andere kant ook eerst uitgehaald. De volgorde kan niet worden veranderd. 2
29
Traffic Control Om HTB duidelijk uit te leggen maakt dit hoofdstuk gebruik van een voorbeeldnetwerk in UML. Dit is hetzelfde netwerk als in hoofdstuk 4, maar voor het overzicht geeft figuur 5.1 het voorbeeldnetwerk nogmaals schematisch weer.
5.2 Netwerkverkeer controleren met rate en ceil Om voorafgaande informatie wat te verduidelijken volgt hier een voorbeeld. In het netwerk van figuur 5.1 bevinden zich twee gebruikers (UML's) die elk met een directe verbinding verbonden zijn met een ethernetpoort van de router. Beide verbindingen moeten gecontroleerd worden met behulp van HTB. Een schematische weergave van hoe je dit netwerk kan controleren zie je in figuur 5.2.
Figuur 5.2: Schema van de instellingen van HTB: rate en ceil Dit kan je instellen met volgende commando's:
tc qdisc add 1 dev eth1 2 root 3 handle 1: 4 htb default 1 5 tc class add 6 dev eth1 parent 1: 7 classid 1:1 8 htb rate 25kbps 9 tc qdisc add dev eth2 root handle 1: htb default 1 tc class add dev eth2 parent 1: classid 1:1 htb \ rate 25kbps ceil 100kbps 10 1
2 3
4
Met tc qdisc add stel je een qdisc in. Je kan geen klassen aanmaken zonder eest een qdisc aan te maken. Voor elke ethernetpoort moet je een aparte qdisk voorzien. Als je een qdisc aanmaakt moet je opgeven voor welke ethernetpoort deze qdisc dient. De term root (of egress) duidt erop dat het gaat om dataverkeer dat de poort (in beide richtingen) verlaat. Dit zijn, met andere woorden, data die reeds in de poort verwerkt zijn en nu verder het netwerk in gestuurd worden. Je kan hier ook ingress gebruiken, maar deze is veel minder uitgebreid dan root. Ingress wordt daarom haast alleen gebruikt om een hoeveelheid data die een poort moet verwerken te verminderen (door bepaalde data te blokkeren voordat ze de poort bereiken) [15]. De handle is niks meer dan een naam waarmee je in de rest van de commando's naar deze qdisc kan verwijzen. Namen van qdiscs en klassen bestaan altijd uit 2 integers, gescheiden door een 30
Traffic Control
5
6 7
8
9
10
dubbelpunt. Voor een qdisc geeft de eerste integer de naam van de qdisc aan. De tweede integer is nul voor een qdisc of wordt gewoon weggelaten. De default-waarde geeft aan welke klasse als standaardklasse gebruikt moet worden. Aangezien dit voorbeeld maar één klasse heeft per qdisc moet tc alle data volgens de specificaties van deze ene klasse behandelen. We komen later nog terug op de optie default, als we een voorbeeld behandelen met meerdere klassen. Met tc class add voeg je een klasse toe aan een bepaalde qdisc. Je moet opgeven aan welke qdisc je een klasse toevoegt. Dit doe je met parent, gevolgd door de handle van de qdisc. Een classid van een klasse komt overeen met een handle voor qdiscs. Het is weer een naam, bestaande uit twee integers. De eerste van de integers duidt hier aan aan welke qdisc de klasse is toegevoegd. De tweede integer dient als een unieke naam voor de klasse. Met rate kan je een snelheid opgeven die tc moet reserveren voor het dataverkeer dat voldoet aan de vereisten van de klasse. In dit geval zijn er geen filters en dus verwerkt tc al het dataverkeer volgens een en dezelfde klasse. Tc beperkt in dit voorbeeld dus het volledige dataverkeer tot 25 kB/s. Met ceil kan je een maximale waarde instellen voor het dataverkeer. Als een bovenliggende klasse een grotere bandbreedte toelaat kan een gebruiker op deze manier meer bandbreedte gebruiken dan bij rate is ingesteld. Merk op dat de bandbreedte bij ceil niet gegarandeerd wordt. Deze extra bandbreedte kan enkel gebruikt worden als ze nergens anders nodig is. Als je geen ceil-waarde opgeeft zal tc voor ceil automatisch dezelfde waarde nemen als je voor rate hebt ingesteld.
Bij deze commando's moet je zeker letten op de manier waarop tc (en niet alleen HTB) snelheden en grootheden noteert. De 25kbps in bovenstaande commando's komt neer op 25 kilobytes per seconde. Als je ergens een grootheid in bits wilt opgeven moet je dit doen door dit languit te schrijven. Een bestand van 10 megabit noteer je in tc dus als 10Mbit [16]. Om de werking van HTB aan te tonen, downloaden we in beide UML's gelijktijdig een bestand. We hebben voor deze test een willekeurig bestand van 50 MB aangemaakt dat we via HTTP naar de UML's kunnen downloaden. We kunnen de resultaten van de test vervolgens aflezen in de grafieken die RRDtool voor ons genereert. eth1 30 k
20 k
10 k
0 17:20
Inkomend verkeer
17:40
18:00
18:20
18:40
19:00
Uitgaand verkeer
Figuur 5.3: Grafiek van een download, begrensd met een rate De grafiek van UML 1-1 (figuur 5.3) toont de snelheid waarmee de UML het bestand van 50 MB gedownload heeft. Je ziet dat de snelheid nergens over de ingestelde 25 kB/s is gegaan. De duur van de download is ongeveer 35 minuten. Dit voorbeeld toont dus aan dat het zeer eenvoudig is om de bandbreedte over een netwerk te beperken met behulp van tc en HTB. 31
Traffic Control
eth2
100 k
50 k
0 17:20
Inkomend verkeer
17:40
18:00
18:20
18:40
19:00
Uitgaand verkeer
Figuur 5.4: Grafiek van een download, begrensd met een rate en een ceil De grafiek in figuur 5.4 toont de snelheid waarmee UML 2-1 hetzelfde bestand gedownload heeft. Je ziet dat de snelheid van deze UML hoger ligt dan die van UML 1-1. De UML haalt snelheden die overeenkomen met de 100 kB/s die je als ceil-waarde hebt ingesteld. Deze ceil-waarde kan enkel behaald worden als op dat moment geen andere transfer bezig is die deze bandbreedte opeist. Aangezien er in dit voorbeeld maar één klasse is, kan een transfer op elk moment de volledige ceil-bandbreedte gebruiken. In dit geval zal UML 2-1 dus altijd aan 100 kB/s kunnen downloaden.
5.3 Meerdere klassen en filters gebruiken Een volgend voorbeeld werkt de klassenstructuur van HTB wat beter uit. In plaats van een algemene beperking van de bandbreedte gaan we in dit voorbeeld de beperking opsplitsen in een beperking voor het HTTP-verkeer en het overige verkeer. Om dit te bereiken moet je twee verschillende subklassen aanmaken met HTB. Het schema in figuur 5.5 geeft mogelijke instellingen van tc weer.
Figuur 5.5: Schema van de instellingen van HTB: meerdere klassen Om deze instellingen te bekomen maken we klassen aan met het tc-commando, zoals in het vorige voorbeeld. Alleen heeft dit voorbeeld meerdere klassen en een filter nodig. De volgende commando's 32
Traffic Control geven aan hoe je de instellingen in orde brengt voor eth1, maar aangezien we voor eth2 exact dezelfde instellingen gebruiken kan je ook dezelfde commando's gebruiken voor eth2. tc qdisc add dev eth1 root handle 1: htb default 3 1 tc class add dev eth1 tc class add dev eth1 rate 40kbps tc class add dev eth1 rate 20kbps
tc filter add 4 dev eth1 protocol ip parent 1:0 prio 1 5 u32 6 \ match ip sport 80 7 0xffff flowid 1:2 8 1
2
3
4
5
6
7
8
De default-waarde geeft aan welke klasse tc standaard moet gebruiken. Als bepaalde data aan geen enkele filter voldoen zal tc de data automatisch aan deze standaardklasse toewijzen. In dit voorbeeld zal tc de klasse 1:3 als standaardklasse gebruiken. Als parent geef je het classid op van de klasse waarvan deze klasse een subklasse is. De hoofdklasse is hier 1:1, dus de twee subklassen moeten beide 1:1 opgeven als parent. Het classid kan je eigenlijk willekeurig kiezen. Maar om overzichtelijk te blijven kan je best even nadenken voordat je een klasse een naam geeft. Het is een stuk overzichtelijker als er enige structuur in je klassen zit. De enige beperking die de klassenamen hebben is dat je enkel integers mag gebruiken. Met tc filter add voeg je een filter toe aan je tc-configuratie. De filter is enkel van toepassing op de poort die je opgeeft bij dev. Een filter is een onderdeel van de tc-tool zelf, en dus niet alleen van HTB. Een prioriteit kan handig zijn als je meerdere klassen gebruikt. De data die overeenkomen met de filter met het laagste getal als prioriteit zullen voorrang krijgen op data met een groter prio-getal. Prio 1 is de hoogste prioriteit. Het type van de filter, u32, geeft aan dat de filter op elk deel van een pakket kan filteren [17]. Andere mogelijke types, zoals /32, zijn niet nodig in onze voorbeelden. Hier gaan we dus ook niet dieper op in. Met sport, of source port, kan je een poortnummer opgeven waarop gefilterd moet worden. Tc zal zo alle data filteren die via deze poort aankomen. In dit voorbeeld hebben we poort 80 opgegeven als sport, wat overeenkomst met de HTTP-poort. Naast sport kan je ook dport gebruiken, voor een destination port. Met flowid geef je op aan welke klasse je de gefilterde data wilt meegeven.
Om de werking van deze instellingen te verduidelijken kunnen we weer een test uitvoeren waarbij de twee UML's een bestand downloaden. UML 1-1 downloadt weer een bestand van 50 MB volgens het HTTP-protocol. UML 2-1 downloadt echter een bestand volgens het FTP-protocol, om duidelijk te maken dat tc deze twee datastromen volgens de specificaties van een andere klasse behandelt. De grafiek in figuur 5.6 toont de downloadsnelheid van de HTTP-transfer in UML 1-1. Zoals verwacht haalt deze transfer een snelheid van 70 kB/s. Dit komt overeen met de ceil-waarde van de klasse 1:2 en tevens met de rate-waarde van de bovenliggende klasse 1:1. De grafiek in figuur 5.7 toont de downloadsnelheid van de FTP-transfer in UML 2-1. Deze snelheid is duidelijk lager dan die van de HTTP-transfer in UML 1-1. De snelheid is hier, zoals verwacht, beperkt tot 50 kB/s. De downloadsnelheid komt overeen met de ceil-waarde van klasse 1:3, omdat er geen andere transfers plaatsvinden in UML 2-1. 33
Traffic Control
eth1
60 k
40 k
20 k
0 13:00
Inkomend verkeer
13:20
13:40
14:00
14:20
14:40
Uitgaand verkeer
Figuur 5.6: Grafiek van een HTTP-download eth2 60 k
40 k
20 k
0 13:00
Inkomend verkeer
13:20
13:40
14:00
14:20
14:40
Uitgaand verkeer
Figuur 5.7: Grafiek van een FTP-download Als in dezelfde UML gelijktijdig een FTP- en een HTTP-transfer zouden plaatsvinden, dan zouden beide transfers minimaal hun rate-snelheid behalen. Wat er dan nog overschiet van de 70 kB/s rate-snelheid van de bovenliggende klasse (1:1) zou tc gelijkmatig verdelen over de twee transfers.
5.4 HTTP-verkeer boosten met burst Het vorige voorbeeld gaf al aan dat het vrij makkelijk is om een netwerk te controleren met behulp van tc en HTB en om verschillende datastromen van elkaar te scheiden. Dit volgende voorbeeld toont een handige methode om het HTTP-verkeer wat vlotter te laten verlopen. HTTP-verkeer bestaat meestal uit pieken. Denk aan een website die je bezoekt. Je moet dan één maal de website aan een zo snel mogelijke snelheid downloaden, waarna er even geen (of minder) HTTP-verkeer is. Pas als je op een volgende link klikt downloadt je browser de volgende hoeveelheid data. Om deze ene piek wat vlotter te laten verlopen kan je met HTB een bepaalde burst toevoegen aan een klasse. Deze burst is een hoeveelheid data die aan een hogere snelheid mag worden afgehaald. Een burst werkt als een teller die optelt als je iets downloadt en die over een bepaalde tijd terug langzaam aftelt. Je kan maar een bepaalde hoeveelheid downloaden. Als deze hoeveelheid bereikt is (als de teller zijn maximum bereikt) daalt de snelheid van de transfer terug. Pas als de teller voldoende gezakt is kan je weer terug downloaden aan de verhoogde snelheid. 34
Traffic Control
Figuur 5.8: Schema van de instellingen van HTB: burst Een schema van een voorbeeldnetwerk met een burst zie je in figuur 5.8. Deze instellingen kan je verwezenlijken met de volgende commando's. Daar de instellingen voor eth1 en eth2 op de burst na identiek zijn, geven we hieronder enkel de instellingen voor eth2 weer. tc qdisc add dev eth2 root handle 1: htb default 3 tc class add dev eth2 rate 50kbps tc class add dev eth2 rate 30kbps tc class add dev eth2 rate 20kbps
tc filter add dev eth2 protocol ip parent 1:0 prio 1 u32 \ match ip sport 80 0xffff flowid 1:2
Om deze instellingen te testen hebben we weer tegelijkertijd in UML 1-1 en UML 2-1 een HTTP-download van een bestand van 50 MB gestart. De grafieken die RRDtool genereert tonen duidelijk de invloed van de burst op eth2 aan. De grafiek van het dataverkeer van UML 1-1, figuur 5.9, vertoont weer het normale gedrag. De downloadsnelheid bedraagt 50 kB/s, wat overeenkomt met de rate-waarde van de bovenliggende klasse 1:1. Merk op dat de snelheid boven de rate-waarde van de eigen klasse kan gaan, maar niet boven die van de bovenliggende klasse. De ceil-waarde van de bovenliggende klasse is hier dus niet van toepassing. In figuur 5.10 zie je de grafiek van de bandbreedte die de UML gebruikt voor de download als tc een burst van 8 MB toelaat. In het begin is er nog niks van de burst opgebruikt en kan de snelheid dus toenemen. In het geval er een burst mogelijk is kan de snelheid boven de rate-snelheid van de bovenliggende klasse uitstijgen. Hij kan echter nooit boven een ceil-waarde uitkomen. De ceil-waarde van klasse 1:2 zorgt er dus voor dat tc de maximale snelheid bij een burst beperkt tot 70 kB/s. Als de burst-teller zijn maximale waarde bereikt voordat de transfer compleet is, moet de snelheid terug zakken. En aangezien de gemiddelde snelheid voor een HTTP-transfer vastligt op 50 kB/s zal de tijdelijke snelheid verder dalen om over de gehele transfer dit gemiddelde te bereiken. Zodra de 35
Traffic Control download de gemiddelde snelheid bereikt, kan de transfer aan deze snelheid blijven verdergaan tot hij volledig voltooid is. Merk op dat deze transfer dus even lang geduurd heeft dan de transfer van hetzelfde bestand zonder burst. Een burst heeft dus enkel een invloed als de hoeveelheid data kleiner is dan de grootte van de burst. eth1 60 k
40 k
20 k
0 22:40
23:00
Inkomend verkeer
23:20
23:40
00:00
00:20
Uitgaand verkeer
Figuur 5.9: Grafiek van een download, zonder burst eth2
60 k
40 k
20 k
0 22:40
23:00
Inkomend verkeer
23:20
23:40
00:00
00:20
Uitgaand verkeer
Figuur 5.10: Grafiek van een download, geboost door een burst Tot slot halen we nog even aan dat je de instellingen van tc op een eenvoudige manier terug kan wissen. Hiervoor is voor elke ethernetpoort slechts een enkel commando nodig. Volgend commando zal alle root- of egress-klassen wissen. Als je ook klassen met ingress gebruikt, moet je het commando nog eens herhalen met ingress in plaats van root. tc qdisc del dev eth1 root
36
Hoofdstuk 6: Scripts In ons project maken we volop gebruik van scripts. Een shellscript is in feite een bestand waarin een aantal commando's onder elkaar staan. Bash voert deze commando's een voor een achter elkaar uit. De commando's in dit script zijn gewoon de commando's die een gebruiker ook in een gewoon commandovenster had kunnen invoeren. Het eerste deel van dit hoofdstuk licht enkele algemene structuren toe die gebruikt worden in de scripts. De drie volgende delen gaan alle scripts binnen het project weergeven en kort bespreken.
6.1 De basis van shellscripts We gebruiken drie verschillende constructies binnen onze scripts. Elke constructie begint met zijn specifieke syntax, gevolgd door een simpel voorbeeld om het gebruik te illustreren.
6.1.1 While-lus De syntax van de while-lus is als volgt: while [ voorwaarde ] do commando done
Het volgende voorbeeld van een while-lus geeft tien keer test als output op het scherm. #!/bin/sh i=1 while [ $i -le 10 ] do echo "test" i=`expr $i + 1` done
6.1.2 For-lus De syntax van de for-lus is als volgt: for variabele in lijst do commando's done
Het volgende voorbeeld van een for-lus voert voor alle waarden in de lijst het echo-commando uit. #!/bin/sh for i in 1 2 3 4 5 do
37
Scripts echo $i done
Ja kan de for-lus kan ook nog op een andere manier opstellen. Deze manier lijkt veel op de syntax van een for-lus in C-code. #!/bin/bash for ((i=1; i<6; i++)) do echo $i done
6.1.3 If-constructie De syntax van de if-constructie gaat als volgt: if voorwaarde then Voer commando's uit else Voer deze commando's uit fi
Een simpel voorbeeld over het gebruik van de if-constructie. Indien $i kleiner is dan 0 krijgen we de output Getal is negatief. Wanneer $i groter is dan 0 wordt de output Getal is positief. #!/bin/sh if [ $i -gt 0 ] then echo "Getal is postitief" else echo "Getal is negatief" fi
6.1.4 Operatoren Hieronder volgt een opsomming van mogelijke operatoren binnen shell en hun eigenlijke betekenis in het Engels. In onze scripts gebruiken we van deze lijst maar enkele operatoren. • -eq staat voor: is equal to • -ne staat voor: is not equal to • -lt staat voor: is less than • -le staat voor: is less than or equal to • -gt staat voor: is greater than • -ge staat voor: is greater than or equal to 38
Scripts
6.1.5 Shebang Elk shellscript begint met een uitdrukking als bijvoorbeeld #!/bin/sh of #!/bin/bash. In de Linuxwereld noemen ze dit een shebang. Het refereert naar een specifiek paar van karakters dat, wanneer gebruikt als de eerste twee karakters van een script, ervoor zorgt dat Linux het script uitvoert met de juiste interpreter1. Hier volgt een opsomming van enkele shebang's. • #!/bin/bash verwijst naar Bash • #!/bin/csh verwijst naar C Shell • #!/bin/ksh verwijst naar Korn Shell • #!/usr/bin/perl verwijst naar Perl • #!/usr/bin/python verwijst naar Python • #!/usr/bin/ruby verwijst naar Ruby Ook #!/bin/sh is zo'n shebang. Deze verwijst op sommige systemen (zoals Solaris) naar Bourne shell. Op Linuxsystemen is er echter meestal geen Bourne shell. Daar is dit dan ook gewoon een link naar een andere shell, zoals bash. We moeten ons bewust zijn dat deze link kan variëren van systeem tot systeem.
6.2 Installatiescripts Dit onderdeel bespreekt de scripts die betrekking hebben op de installatie van het project.
6.2.1 install.sh Dit script voorziet een makkelijke manier om het hele project te installeren op een pc met een Linuxdistributie die op Debian gebaseerd is. Zowel Debian zelf als een variant van Ubuntu komen hiervoor in aanmerking. #!/bin/sh ##variabelen path=${HOME}/GFproject map=$(pwd)
Het script declareert hier twee variabelen die het in de rest van de commando's gebruikt. De variabele path geeft het pad naar de map waarin het project geïnstalleerd zal worden. Deze map varieert voor elke gebruiker die de installatie uitvoert. De variabele map houdt de plaats bij waar de gebruiker zich bevindt op het moment dat hij de installatie start. ##een alias creëren om het project overal te kunnen starten echo >> $HOME/.bashrc echo "alias gfstart=\"cd $path && ./project.sh\"" >> $HOME/.bashrc echo "alias gfstop=\"cd $path && ./stop.sh\"" >> $HOME/.bashrc 1
Een interpreter is een speciaal computerprogramma dat programma's verwerkt die in een specifieke programmeertaal geprogrammeerd zijn. De interpreter voert het programma onmiddellijk uit door de regels code direct om te zetten in instructies die de processor begrijpt [18].
39
Scripts Vervolgens maakt het script twee aliassen aan om het project van overal te kunnen starten en stoppen. De alias gfstart gaat eerst naar de projectmap en voert daar het opstartscript uit. De andere alias gaat naar de projectmap en voert het stopscript uit. ##sources.list aanpassen (universe + multiverse uit commentaar halen) echo "sources.list aanpassen" in=false while [ "$in" = "false" ] do echo "Heeft u reeds een aangepaste sources.list? [n,y]: " read input if [ "$input" = "y" ] || [ "$input" = "n" ]; then in=true fi done if [ "$input" = "n" ]; then cat /etc/apt/sources.list | sed 's/#//' | \ sed 's/#/##/' > sources.list sudo mv /etc/apt/sources.list /etc/apt/sources.list.backup sudo mv sources.list /etc/apt/sources.list fi
Om de nodige software voor het project te kunnen vinden moet het script ervoor zorgen dat de juiste repositories2 aanwezig zijn. Dit doet het door in de standaard lijst van bronnen de bronnen die in commentaar staan uit de commentaar te halen. Hierdoor neemt de hoeveelheid installeerbare software voor de distributie toe. Het installatiescript stelt de vraag of de gebruiker al een aangepaste bronnenlijst heeft. Als dat zo is hoeft het deze bronnenlijst niet meer aan te passen. Indien het antwoord niet overeenkomt met een juist mogelijk antwoord (y of n), zal de while-lus de vraag herhalen tot de gebruiker een geldig antwoord geeft. ##benodigde software installeren echo "apt-get update en install bridge-utils uml-utilities" sleep 10s sudo apt-get update sudo apt-get -y install bridge-utils uml-utilities
Ons script installeert vervolgens met behulp van apt-get de nodige Debian-pakketten om een virtueel netwerk te kunnen emuleren in de host-pc. De optie -y wil zeggen dat apt-get de gebruiker niet telkens moet vragen of het al dan niet toelating heeft om de pakketten te installeren. ##installatiemap maken echo "juiste mappen maken en bestanden overnemen" sleep 10s mkdir -p $path ##gedeelde mappen installeren 2
Een repository is een centrale plaats waar data, meestal in de vorm van kant en klare pakketten, opgeslagen en onderhouden worden [19].
40
Scripts sudo cp -vr uml/ /mnt/
Hier wordt een map aangemaakt waarin het script het hele project gaat uitpakken en nadien ook gaat uitvoeren. De gedeelde mappen tussen de host-pc en de UML's worden gekopieerd naar de map /mnt/. ##belangrijke bestanden overnemen van de host sudo cp /etc/resolv.conf /mnt/uml/init_router/resolv.conf sudo cp /etc/resolv.conf /mnt/uml/init/resolv.conf sudo cp /etc/apt/apt.conf /mnt/uml/init_router/apt.conf sudo cp /etc/apt/apt.conf /mnt/uml/init/apt.conf sudo cp /etc/network/interfaces /mnt/uml/interfaces_original
Om het netwerk en de internetverbinding goed op poten te zetten kopieert het script een aantal belangrijke bestanden van de host-pc naar de gedeelde mappen. Resolv.conf is een configuratiebestand waarin het IP-adres van de dns3-server staat. Er kunnen eventueel ook meerdere IP-adressen in staan. Het volgende configuratiebestand dat gekopieerd moet worden is apt.conf. Dit bestand omvat de configuratie van apt-get. Indien de host-pc een internetverbinding heeft via een proxyserver, zoals op de KHLim het geval is, dan staan de proxygegevens in dit bestand. ##schrijf- en leesrechten van de bestanden aanpassen sudo chmod a+rwx /mnt/uml/uml/ sudo chmod a+rw /mnt/uml/uml/*RDY
Binnen de map /mnt/uml/ bevindt zich nog een map uml/. Deze map is zo genoemd omdat ze de bedoeling heeft om bestanden van de UML over te zetten naar de host. Als we vanuit de UML hierin willen kunnen schrijven moeten we zorgen dat iedereen de rechten heeft om in deze map te schrijven. Dit doen we met het chmod-commando. Met de optie a+rwx kennen we aan alle bestanden in de map uml/ lees-, schrijf- en uitvoerrechten toe. ##opstartscripts in de projectmap zetten cp -r scripts/* $path/ cp uninstall.sh $path/ ##images in de projectmap zetten tar -xvzf images.tar.gz -C $path
De scripts worden gekopieerd naar de aangemaakte projectmap. Het archief van de image-bestanden wordt uitgepakt naar de projectmap. ##linux guestkernel uitpakken en compileren echo "linux guestkernel uitpakken en compileren" sleep 10s tar -C $path -xvzf linux-2.6.20.1.tar.gz cd $path/linux-2.6.20.1/ make mrproper 'ARCH'=um cp -v $map/.config $path/linux-2.6.20.1/. make linux 'ARCH'=um 3
Het Domain Name System (DNS) is het systeem en protocol van de vierde laag van het OSI-model dat op het internet voornamelijk gebruikt wordt om domeinnamen naar IP-adressen te vertalen en omgekeerd. Zie hoofdstuk 3 voor uitleg over het OSI-model.
41
Scripts cd .. ln -s linux-2.6.20.1/linux linux
Hier wordt het archief van de guest-kernel uitgepakt naar de projectmap. Vervolgens kopieert het script het configuratiebestand .config waarin al onze opties staan aangevinkt naar die map. Daarna compileren we de kernel ter plekke. Dit resulteert in een uitvoerbaar bestand dat linux heet. We maken ook een link naar dit bestand in een bovengaande map. ##linux hostkernel uitpakken en installeren in=false while [ "$in" = "false" ] do echo "wilt u de voorgecompileerde hostkernel met de skaspatch installeren? [n,y]:" echo "we kunnen niet garanderen dat dit werkt" read input if [ "$input" = "y" ] || [ "$input" = "n" ]; then in=true fi done if [ "$input" = "y" ]; then cd $map sudo dpkg -i linux-headers-2.6.17.14-ubuntu1-gfproject-skas3-v9pre9_2.6.17.1-11.37_i386.deb sudo dpkg -i linux-image-2.6.17.14-ubuntu1-gfproject-skas3-v9pre9_2.6.17.1-11.37_i386.deb fi
Eerst stelt het script in een while-lus aan de gebruiker de vraag of hij onze gepatchte kernel wilt installeren. De gebruiker krijgt deze keuze omdat het niet zeker is dat onze kernel op elk systeem werkt. Als de gebruiker instemt pakt het script de pakketten met de Linuxkernel uit en installeert het de kernel. Omdat het hier om .deb-pakketten gaat kan je met één enkel commando een volledig pakket uitpakken en de inhoud installeren. ##bridge.sh in init.d kopieren, de nodige rechten geven en toevoegen ##aan rc.local zodat dit bij booten uitgevoerd wordt echo "bridge.sh in de juiste map plaatsen" sleep 10s sudo mv ${path}/bridge.sh /etc/init.d/. sudo update-rc.d bridge.sh defaults sudo $map/rc.local.sh
We verplaatsen het script bridge.sh van de projectmap naar de map /etc/init.d/. Deze map staat vol met uitvoerbare scripts. Het update-commando voegt bridge.sh toe aan de opstartscripts van elk runlevel4. Hierdoor zal bridge.sh altijd gestart kunnen worden, onafhankelijk van het runlevel waarin we vertoeven. Omdat we bridge.sh op het einde van het bootproces willen uitvoeren moeten we het opstartcommando van het script in het bootscript /etc/rc.local invoegen. Dit wordt gedaan door het script rc.local.sh. We starten hier een script met sudo opdat alle commando's die zich binnen dit script bevinden als root uitgevoerd zullen worden. 4
De term runlevel verwijst naar een werkingsmode van het Linux besturingssysteem.
42
Scripts ##pc rebooten echo "********** rebooting **********" in=false while [ "$in" = "false" ] do echo "Kies y om nu te rebooten, kies n om later te rebooten" read input if [ "$input" = "y" ] || [ "$input" = "n" ]; then in=true fi done if [ "$input" = "y" ]; then sudo reboot fi
Een laatste stap van install.sh vraagt aan de gebruiker of hij zijn pc opnieuw wilt opstarten, zodat alle aanpassingen volledig worden doorgevoerd. Indien de gebruiker hier negatief op antwoord zal hij zijn pc achteraf zelf opnieuw moeten opstarten.
6.2.2 rc.local.sh Het script install.sh zal dit script starten met sudo. Hierdoor kunnen we de commando's die hierin staan met rootrechten uitvoeren. #!/bin/sh cp /etc/rc.local /etc/rc.local_orig cat /etc/rc.local | sed 's/exit 0/\/etc\/init.d\/bridge.sh/g' \ >> /tmp/rc.local echo "" >> /tmp/rc.local echo "exit 0" >> /tmp/rc.local cp -f /tmp/rc.local /etc/rc.local chmod a+x /etc/rc.local
Als eerste kopieert dit script de oorspronkelijke rc.local naar een nieuw bestand als back-up. Vervolgens vervangt het de laatste regel van het script dat altijd uit exit 0 bestaat door het pad naar het bridge.sh-script. Verder voegt het exit 0 terug toe aan het einde van het nieuwe script. Het verplaatst tenslotte rc.local nog van de tijdelijke naar de juiste map en geeft alle gebruikers uitvoerrechten.
6.2.3 uninstall.sh Dit script voorziet een makkelijke manier om het hele project te verwijderen. ##bridge.sh niet meer uitvoeren bij het booten sudo update-rc.d -f bridge.sh remove sudo rm -f /etc/init.d/bridge.sh cat /etc/rc.local | sed 's/\/etc\/init\.d\/bridge\.sh//g' >> /tmp/rc.local
43
Scripts sudo mv /tmp/rc.local /etc/rc.local
In een eerste stap verwijdert dit script alle verwijzingen naar bridge.sh uit de opstartscripts van elk runlevel. Vervolgens verwijdert het bridge.sh zelf en wist het het opstartcommando uit rc.local. ##aliassen verwijderen cat ${HOME}/.bashrc | sed 's/alias \ gfstart="cd \/home\/geert\/GFproject && \.\/project\.sh"//g' | sed \ 's/alias gfstop="cd \/home\/geert\/GFproject && \.\/stop\.sh"//g' \ >> /tmp/.bashrc sudo mv /tmp/.bashrc ${HOME}/.bashrc ##de projectmappen verwijderen sudo rm -rf ${HOME}/GFproject/ sudo rm -rf /mnt/uml/
In de volgende stappen wist het script alle aliassen en projectmappen die install.sh eerder heeft aangemaakt. ##de kernel met skas-patch verwijderen sudo dpkg -r linux-image-2.6.17.14-ubuntu1-gfproject-skas3-v9-pre9 sudo dpkg -r linux-headers-2.6.17.14-ubuntu1-gfproject-skas3-v9-pre9
Als laatste wist het script de kernel met de skas-patch, als install.sh deze geïnstalleerd heeft.
6.3 Opstartscripts Dit deel bespreekt de verschillende opstartscripts die het project gebruikt. De scripts die hieronder opgesomd zijn spelen allemaal hun rol bij het opstarten van het volledige project nadat het correct geïnstalleerd is.
6.3.1 bridge.sh Het script bridge.sh wordt automatisch uitgevoerd op het einde van het bootproces van de host-pc, vlak voordat een gebruiker inlogt op de pc. Om te verifiëren dat bridge.sh gestart is, kan je met het commando ifconfig de toestand van de ethernetpoorten opvragen. #!/bin/sh ip=$(ifconfig eth0|grep "inet addr"|sed 's/.*addr://g'| \ sed 's/ Bcast.*//g') mask=$(ifconfig eth0|grep "inet addr"|sed 's/.*Mask://g') default=$(ip route show|grep "default"|sed 's/default via //g'| \ sed 's/ dev.*//g')
De eerste stap van het bridge.sh-script bestaat eruit om de bestaande netwerkgegevens op te vragen van de host-pc, met name het IP-adres, het netmask en de default gateway. Het script vraagt via een gewoon commando de gegevens op en filtert met behulp van grep en sed de nodige informatie uit de gekregen output. Grep zorgt ervoor dat alleen de gewenste regel van de output overblijft terwijl sed alle overbodige informatie uit de regel verwijdert. De overgebleven informatie slaan we op in een variabele. 44
Scripts De volgende commando's [6] maken gebruik van de informatie in deze variabelen om de bridge op te starten. sudo sudo sudo sudo sudo sudo sudo sudo sudo 1 2
Dit commando activeert IP-forwarding op de host-pc. Hier wordt de ethernetpoort van de host-pc naar een tijdelijke IP-vrije toestand gereset. Alle netwerkactiviteiten zullen tijdelijk stilliggen. Deze regel definieert een nieuwe virtuele bridge, uml-bridge. Dit commando bepaalt de vertraging die optreedt als je pakketten doorstuurt. Dit commando geeft op wat de hello-tijd is. Een router die juist opgestart wordt begint hello-pakketten te versturen in het netwerk om te melden dat hij nieuw is. Op deze manier leren andere routers dat er een nieuwe router in het netwerk aanwezig is. Dit commando zet Spanning Tree Protocol (STP) af. STP is een protocol van de tweede OSI-laag en zorgt ervoor dat er geen lussen voorkomen in het netwerk. Een volgend commando geeft het IP-adres van de host aan de bridge en activeert deze. Het voorlaatste commando voegt een default gateway toe. En tenslotte hangt dit laatste commando de bridge aan de ethernetpoort.
6.3.2 interfaces.sh Het script uml.sh start interfaces.sh en geeft hierbij twee variabelen mee die bepalen tot welk subnetwerk de UML zal behoren en de hoeveelste UML hij zal zijn binnen dit subnetwerk. Deze variabelen worden in de bestanden SUBNET en UML_DEV gestoken zodat de opgestarte UML zichzelf achteraf kan identificeren. Vervolgens maakt een volgend commando het configuratiebestand interfaces klaar door een vast IP-adres toe te wijzen aan de UML. Dit adres hangt af van het nummer van de UML en het subnetwerk waarin deze zich bevindt. #!/bin/sh echo $1>/mnt/uml/init/SUBNET echo $2>/mnt/uml/init/UML_DEV cat /mnt/uml/init/interfaces | \ sed 's/"subnet"/'$1'/' | \ sed 's/"ethernetdevice"/'$1$2'/' >/mnt/uml/init/interfaces$1_$2
6.3.3 uml.sh Dit script bevat het opstartcommando voor de gewone UML's. Het heeft twee variabelen nodig, die dienen om de UML te identificeren. #!/bin/sh
De eerste regel voert interfaces.sh uit dat een juist configuratiebestand maakt voor de UML. Het UML-script geeft automatisch zijn twee variabelen verder aan het interfaces-script. Een volgend commando, over meerdere regels, start de UML. Dit commando bestaat uit meerdere delen, waarvan de meeste betrekking hebben op de virtuele hardware van de UML. Als eerste geeft het een unieke naam aan de UML mee door middel van umid. Vervolgens wijst het een virtuele harde schijf met een bijhorend COW-bestand toe. Met root, vervolgens, vertelt het commando van welke virtuele schijf de UML moet opstarten. Dit wordt meestal gedaan als de virtuele hardware uit meerdere virtuele harde schijven zou bestaan. Met behulp van con verbindt dit commando de UML met een xterm, dit is een apart terminalvenster waar de gebruiker over kan beschikken. Vervolgens wijst het 80 MB aan RAM-geheugen toe aan de UML met de optie mem. Als laatste bevat het opstartcommando de virtuele poort waarover de UML kan beschikken. Deze poort wordt gekoppeld aan een virtuele switch die als een proces gestart moet zijn alvorens deze UML opstart.
6.3.4 router.sh Dit script bevat het opstartcommando voor de router. Omdat dit een uitgebreid commando is leek het een goed idee om hier een script van te maken. Daar komt nog eens bij dat het commando verandert, afhankelijk van hoeveel UML's er met de router verbonden zijn. Het opstartscript project.sh genereert dit script en het commando met alle nodige opties. #!/bin/sh ./linux umid=UML-R mem=128M con=xterm ubd0=.mycows/mycow_router,Debian-router_fs root=/dev/ubda eth0=tuntap,uml-conn1,FE:FD:01:00:00:01 eth1=daemon,,unix,/tmp/switch-1 eth2=daemon,,unix,/tmp/switch-2
\ \ \ \
Dit commando is in principe hetzelfde opstartcommando als dat van de UML, op enkele verschillen na. Zo heeft de router een andere unieke naam en beschikt hij over meer geheugen dan de gewone UML. Dit geheugen is nodig omdat er binnen de router een webserver draait en omdat de router op regelmatige tijdstippen data moet opvragen en grafieken moet genereren. Verder beschikt de router over een andere virtuele harde schijf dan de UML, met name de router-image die van extra software voorzien is. De router beschikt over meerdere virtuele ethernetpoorten. De standaardpoort eth0 is via het tunnelingsprincipe verbonden met de virtuele bridge zodat er een connectie met internet mogelijk is. Het commando geeft aan eth0 ook een zelf gekozen mac-adres mee. Zonder dit adres zal de DNS-server van het netwerk geen IP-adres kunnen toekennen aan deze poort. De andere twee poorten dienen voor een connectie met het private netwerk. Deze connectie maakt gebruik van een virtuele switch, één voor elke poort. In dit geval zijn er twee verbindingen met de router, maar afhankelijk van de opties die de gebruiker aan project.sh meegeeft kan dit aantal veranderen. 46
Scripts
6.3.5 init.sh Het project bevat twee scripts met de naam init.sh, één voor de client en één voor de router. De UML's voeren dit script uit op het einde van hun boot-proces. Deze twee scripts zorgen voor een juiste hostname en venstertitel voor de UML. Vervolgens kopiëren ze nog enkele configuratiebestanden van de gemounte map naar de map waar ze thuishoren. #!/bin/sh echo -n $'\e]0;'UML_ROUTER$'\a' /bin/hostname UML_ROUTER cp /mnt/host/init_router/resolv.conf /etc/ cp /mnt/host/init_router/interfaces /etc/network/ cp /mnt/host/init_router/apt.conf /etc/apt/ /etc/init.d/networking restart iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE echo 'y' > /mnt/host/uml/ROUTER_RDY echo '1' > /proc/sys/net/ipv4/ip_forward
Het init-script van de router moet maskerade instellen. Zie hoofdstuk 3 voor uitleg over maskerade. Vervolgens schrijft het een y weg in het bestand ROUTER_RDY om aan project.sh aan te geven dat het booten van de router voltooid is. Tenslotte schrijft het nog een 1 naar het bestand ip_forward om zo IP-forwarding te activeren. #!/bin/sh SUBNET=$(cat /mnt/host/init/SUBNET) UML_DEV=$(cat /mnt/host/init/UML_DEV) echo -n $'\e]0;'UML${SUBNET}_${UML_DEV}$'\a' echo 'SUBNET='$SUBNET echo 'UML_DEV'=$UML_DEV /bin/hostname UML"$SUBNET"_"$UML_DEV" cp /mnt/host/init/resolv.conf /etc/ cp /mnt/host/init/interfaces"$SUBNET"_"$UML_DEV" \ /etc/network/interfaces cp /mnt/host/init/apt.conf /etc/apt/ /etc/init.d/networking restart echo 'y' > /mnt/host/uml/UML_RDY
Het init-script van de client-UML's moet enkel nog meedelen aan project.sh dat het bootproces voltooid is. Dit doet het weer door een y weg te schrijven in het daarvoor voorziene bestand, UML_RDY.
6.3.6 project.sh Dit is het script waarmee gebruikers het project volledig kunnen opstarten zonder alle commando's manueel te moeten ingeven. 47
Scripts #!/bin/sh test=$(ifconfig | grep 'uml-bridg' | sed 's/bridg.*/bridg/g') if [ "$test" != "uml-bridg" ]; then echo "Het bridge-script heeft niet gewerkt" echo "Het GF-project wordt verlaten..." exit 0 fi
Het eerste stuk van het projectscript dient om te controleren of de virtuele bridge van de host-pc wel degelijk bestaat. Indien deze niet zou bestaan is er helemaal geen internetverbinding mogelijk. In dit geval wordt de verdere uitvoering van het script afgebroken. echo "Hoeveel subnetten: [0-9]" read SUBNET while [ $SUBNET -gt 9 ] do SUBNET=0 echo "Het aantal subnetten is te groot." echo "Kies een waarde tussen 0 en 9: " read SUBNET done echo "Hoeveel UML's per subnet: [0-9]" read UMLs while [ $UMLs -gt 9 ] do echo "Dit aantal UML's is te groot." echo "Kies een waarde tussen 0 en 9: " read UMLs done sudo ./clean.sh
Dit deel stelt de vraag aan de gebruiker hoeveel achterliggende netwerken hij graag zou willen emuleren. Als tweede vraagt het hoeveel virtuele client-pc's het script moet starten voor elk achterliggend netwerk. Vervolgens wist het met clean.sh alle bestanden die tijdens een eerdere uitvoering van het hele project zijn aangemaakt. Dit clean-script wordt elke keer door project.sh gegenereerd. Hierdoor blijft het script altijd up-to-date. sudo sudo sudo sudo sudo
Van deze commando's creëert het eerste een nieuwe tunnel voor de router naar de virtuele bridge met de naam uml-conn1. Het volgende commando verandert het apparaat van groep. Daarna verandert chmod de gebruikersrechten voor het apparaat. De 666 heeft dezelfde betekenis als a+rw, wat wil zeggen dat elke gebruiker zowel lees- als schrijfrechten krijgt. Vervolgens reset een volgend commando het 48
Scripts IP-adres van uml-conn1 naar 0.0.0.0. Door de optie promisc up zorgt het ervoor dat er geen pakketten van uml-conn1 verloren gaan en dat deze gewoon verder worden gestuurd [6]. sudo $(pwd)/interfaces_router.sh $SUBNET mkdir .mycows rm clean.sh
Het script interfaces_router.sh maakt het configuratiebestand interfaces voor de router. Dit bestand beschrijft hoe de toegewezen ethernetpoorten geconfigureerd zijn. Voor de standaardethernetpoort wil dit zeggen dat het IP-adres toegekend wordt door de DNS-server binnen het netwerk. De andere ethernetpoorten krijgen een vast IP-adres toegewezen want ze hebben geen verbinding met de DNS-server. Vervolgens maakt het script de onzichtbare map .mycows aan waar het project alle COW-bestanden in opslaat. Als laatste verwijdert het de oude clean.sh, omdat deze verder opnieuw aangemaakt zal worden. aantal=1 while [ $aantal -le $SUBNET ] do uml_switch -unix /tmp/switch-$aantal& aantal=`expr $aantal + 1` done
Deze while-lus start het aantal nodige virtuele switches dat overeenstemt met het aantal subnetwerken dat de gebruiker heeft gekozen. aantal=1 echo '#!/bin/sh' > router.sh echo '' >> router.sh echo './linux umid=UML1 mem=64M con=xterm \' >> router.sh echo ' ubd0=.mycows/mycow_router,Debian-router_fs root=/dev/ubda \' >> router.sh echo ' eth0=tuntap,uml-conn1,FE:FD:01:00:00:01 \' >> router.sh while [ "$aantal" -le "$SUBNET" ] do echo ' eth'$aantal'=daemon,,unix,/tmp/switch-'$aantal' \' >> router.sh aantal=`expr $aantal + 1` done sudo chmod a+x router.sh echo 'n' > /mnt/uml/uml/ROUTER_RDY ./router.sh&
Dit gedeelte van het script genereert router.sh. Dit script is variabel omdat het voor elk subnetwerk een virtuele ethernetpoort moet opgeven in het opstartcommando van de router. Vervolgens maakt chmod het router-script uitvoerbaar voor iedereen. Verder schrijft het script een n weg in het bestand ROUTER_RDY. Dit bestand laat project.sh wachten tot de router volledig is opgestart. Op het einde start het script het zopas aangemaakte router.sh-script op als een apart proces. echo "sudo rm router.sh" > clean.sh echo "sudo rm /tmp/switch-*" >> clean.sh
Hier worden de eerste commando's in clean.sh geschreven. Deze commando's verwijderen de juist aangemaakte bestanden die nodig zijn voor de router. while [ "$(cat /mnt/uml/uml/ROUTER_RDY)" != y ] do sleep 2s done
Deze while-lus vraagt elke twee seconden de inhoud van het bestand ROUTER_RDY op. Zolang in dit bestand een n staat blijft project.sh in deze while-lus hangen. Pas als de router volledig is opgestart en een y heeft weggeschreven in ROUTER_RDY kan dit script verdergaan. net=1 while [ $net -le $SUBNET ] do uml=1 while [ $uml -le $UMLs ] do echo 'n'>/mnt/uml/uml/UML_RDY ./uml.sh $net $uml& echo "sudo rm /mnt/uml/init/interfaces${net}_${uml}" >> clean.sh while [ "$(cat /mnt/uml/uml/UML_RDY)" != y ] do sleep 2s done uml=`expr $uml + 1` done net=`expr $net + 1` done
Deze geneste while-lussen starten het juiste aantal client-UML's op per subnetwerk. Het maakt weer gebruik van hetzelfde principe als hierboven om project.sh te laten wachten tot een UML volledig opgestart is. Dit keer gebruikt het hiervoor het bestand UML_RDY. Elke UML start op als een apart proces. De twee variabelen die dit script meegeeft aan het opstartscript van de UML staan voor het subnetwerk waartoe de UML behoort en het toegewezen UML-nummer binnen een subnetwerk. echo "sudo rm -r .mycows/">>clean.sh sudo chmod a+x clean.sh
Als voorlaatste stap voegt dit script een commando aan clean.sh toe dat de verborgen map met de COW-bestanden verwijdert. Helemaal op het einde maakt chmod het clean-script nog uitvoerbaar voor alle gebruikers.
6.3.7 stop.sh De eerder aangemaakte alias gfstop roept dit script op. Het laat de gebruiker toe om op een snelle manier het hele project stil te leggen. #!/bin/sh
50
Scripts
SUBNET=$(cat /mnt/uml/init/SUBNET) UMLs=$(cat /mnt/uml/init/UML_DEV) net=1 while [ $net -le $SUBNET ] do uml=1 while [ $uml -le $UMLs ] do umlpid=$(cat ${HOME}/.uml/UML${net}_${uml}/pid) kill $umlpid sleep 1s uml=`expr $uml + 1` done net=`expr $net + 1` done routerpid=$(cat ${HOME}/.uml/UML1/pid) kill $routerpid
User-Mode Linux slaat van elke UML een pid5 op in de map ${HOME}/.uml/. Een while-lus vraagt één voor één alle pid's op en legt vervolgens met het kill-commando de overeenstemmende UML stil.
6.4 Uitvoeringsscripts Dit onderdeel legt de scripts uit waarmee gebruikers de onderdelen van het project kunnen uitvoeren die in de UML's moeten lopen. Om het de gebruiker gemakkelijk te maken is er in de router ook een alias gf voorzien die het juiste script start.
6.4.1 database.sh Dit script maakt een database aan voor elke ethernetpoort die aanwezig is in de router. Het nummer van de poort wordt meegegeven als parameter $1 wanneer het script gestart wordt. #!/bin/sh rrdtool=/usr/local/rrdtool-1.2.19/bin/rrdtool rm -f ${HOME}/databases/eth${1}.rrd let "start=$(date +%s)/60*60" ${rrdtool} create ${HOME}/databases/eth${1}.rrd \ --step 60 \ --start ${start} \ DS:input:COUNTER:120:U:U \ DS:output:COUNTER:120:U:U \ RRA:AVERAGE:0.5:1:300 \ RRA:AVERAGE:0.5:5:600 \ RRA:AVERAGE:0.5:30:600 \ RRA:AVERAGE:0.5:120:600 \ 5
Process ID: Dit is een uniek nummer dat Linux aan alle lopende processen toewijst als identificatie.
51
Scripts RRA:AVERAGE:0.5:1440:400
Als eerste maakt dit script een variabele aan die het pad naar het commando van RRDtool bijhoudt. Vervolgens verwijdert het de databases, die nog aanwezig zouden kunnen zijn van een vorige test. Verder maakt het script met let een variabele aan die een starttijd berekent voor de verschillende databases. Deze starttijd, in seconden sinds epoch, zal altijd deelbaar zijn door 60 seconden. Dit is niet verplicht, maar aangezien een script alle databases ook gaat updaten op een tijd die deelbaar is door 60 seconden, maakt dit het iets makkelijker om tijden uit te rekenen. Een uitgebreide uitleg over het laatste commando, om de database aan te maken, kan je in hoofdstuk 4 terugvinden.
6.4.2 picture.sh Dit script genereert een grafiek voor het dataverkeer van de standaardethernetpoort eth0 van de router. Een gelijkaardig script, picture-details.sh, werkt analoog om meerdere verschillende grafieken aan te maken voor dezelfde ethernetpoort. Het is dan ook voldoende om enkel dit eerste script hier weer te geven. #!/bin/sh rrdtool=/usr/local/rrdtool-1.2.19/bin/rrdtool ${rrdtool} graph /var/www/pics/eth0.png --start -86400 -t "eth0" -z -f "%s aanmaken" DEF:inoctets=${HOME}/databases/eth0.rrd:input:AVERAGE DEF:outoctets=${HOME}/databases/eth0.rrd:output:AVERAGE AREA:inoctets#00FF00:"Inkomend verkeer" LINE1:outoctets#FF0000:"Uitgaand verkeer"
\ \ \ \ \
Dit script gebruikt het graph-commando van RRDtool om een grafiek aan te maken. Meer uitleg over dit commando vind je terug in hoofdstuk 4. Het script picture-details.sh maakt met ditzelfde commando, maar met telkens een andere start- en eindtijd, andere grafieken van dezelfde data.
6.4.3 program.sh Dit script zal als een proces starten en zal gedurende het hele project constant blijven lopen. Het gaat op een vast tijdsinterval informatie over het dataverkeer opvragen met behulp van SNMP en deze verwerken en opslaan in de daarvoor aangemaakte databases. #!/bin/sh subnets=$(cat /etc/network/interfaces | grep SUBNET | \ sed 's/# SUBNET = //') rrdtool=/usr/local/rrdtool-1.2.19/bin/rrdtool
Als eerste stap maakt het script twee variabelen aan. De eerste zal het aantal subnetwerken bijhouden, terwijl de tweede het pad naar het rrdtool-commando bijhoudt. while [ 1 ] do aantal=0 while [ $aantal -le $subnets ]
Omdat dit script moet blijven lopen tot de gebruiker de router stillegt, heeft het een oneindige while-lus. Het script vraagt voor elke ethernetpoort apart de plaats in de MIB-boom op. Daarna kan het aan de hand van deze plaats het aantal binnenkomende en uitgaande pakketten opvragen. Deze data slaat het vervolgens op in de database van de bijhorende poort. In een volgende stap start het de twee scripts die de figuren voor eth0 genereren, gevolgd door scripts die de figuren genereren voor alle andere ethernetpoorten. Als laatste zal het script wachten tot de systeemtijd weer een tijd bereikt die deelbaar is door 60 seconden, om vervolgens de volledige inhoud van de lus nogmaals te herhalen.
6.4.4 rrdtool.sh Als de gebruiker de alias gf ingeeft zal dit script starten. Dit script zal op zijn beurt de twee voorgaande scripts starten, van zodra deze nodig zijn. #!/bin/sh subnets=$(cat /etc/network/interfaces | grep SUBNET | \ sed 's/# SUBNET = //') rm -fr /var/www/pics/ mkdir -p /var/www/pics mkdir -p ${HOME}/databases
Het eerste deel van het script omvat een aantal voorbereidingen om het project aan te vatten. Als eerste vraagt het het aantal achterliggende netwerken op dat in het interfaces-bestand verwerkt zit. Het verwijdert vervolgens alle figuren die nog aanwezig zouden zijn van een vorige uitvoering. Verder maakt het twee mappen aan waarin het later allerlei bestanden, namelijk de figuren en de databases, kan opslaan. teller=0 while [ $teller -le $subnets ] do ./database.sh ${teller} teller=`expr $teller + 1` done
53
Scripts In deze while-lus maakt het script de nodige databases aan voor het hele project. Voor elke ethernetpoort voorziet het een aparte database. rm -f /var/www/index.html echo '' > /var/www/index.html echo '' >> /var/www/index.html echo '' >> /var/www/index.html echo '' >> /var/www/index.html echo '' >> /var/www/index.html echo '' >> /var/www/index.html echo ' ELO09: network interfaces' >> /var/www/index.html echo ' ' >> /var/www/index.html echo ' <meta http-equiv="refresh" content="60">' >> /var/www/index.html echo '' >> /var/www/index.html echo '' >> /var/www/index.html echo '' >> /var/www/index.html echo '' >> /var/www/index.html echo '
ELO09: network interfaces
' >> /var/www/index.html echo '' >> /var/www/index.html teller=0 while [ $teller -le $subnets ] do echo "
De code hierboven geneert een indexpagina voor op de webserver. Deze indexpagina is opgebouwd in XHTML en bestaat uit een titel met daaronder een aantal algemene figuren. Elk van die figuren stemt overeen met een ethernetpoort en vormt een link naar een pagina met detailfiguren voor deze poort. teller=0 while [ $teller -le $subnets ] do echo '' > /var/www/eth${teller}.html echo '' >> /var/www/eth${teller}.html
In deze while-lus maken we voor elke ethernetpoort een XHTML-pagina waar drie figuren in staan. Deze figuren zijn groter dan de algemene figuren en bevatten meer details. Als laatste wordt het script program.sh als een proces gestart en komt de gebruiker terug in zijn home-map terecht.
55
Hoofdstuk 7: Besluit Het doel van dit eindwerk is een virtuele testomgeving ontwerpen waarin gebruikers op een veilige en goedkope manier nieuwe systemen en protocols kunnen uittesten. Deze testomgeving moet bestaan uit een netwerk van een router met meerdere virtuele pc's. De gebruiker moet op een eenvoudige manier enkele gegevens in verband met het dataverkeer over het netwerk kunnen opvragen. En indien gewenst kan de gebruiker het dataverkeer over het netwerk ook volledig regelen.
7.1 Samenvatting Als testomgeving maken we gebruik van User-Mode Linux, waarmee we op één enkele pc een volledig netwerk met een router en verschillende pc's kunnen emuleren. Met behulp van User-Mode Linux kunnen we de router en de verschillende pc's configureren zoals dat met echte Linuxsystemen kan. We kunnen eenvoudig instellen welke hardware de pc's moeten hebben en welke software er allemaal in het besturingssysteem aanwezig moet zijn. Een volgende stap is dat de verschillende pc's in het virtuele netwerk een verbinding hebben met het internet. Hiervoor hebben we een virtuele netwerkbridge aangemaakt op onze host-pc waarop we zowel de gewone pc als de virtuele router met behulp van een tunnel kunnen verbinden. Via deze bridge kunnen beide toegang krijgen tot het internet, eventueel via een lokaal intranet waarop de pc is aangesloten. De UML's in het netwerk kunnen op hun beurt via de UML-router een internetverbinding verkrijgen. Een algemeen schema met de structuur van ons virtueel netwerk kan je zien in figuur 7.1.
Figuur 7.1: Algemeen schema van het virtuele netwerk in de testopstelling Als het virtuele netwerk volledig in orde is kunnen we ons bezighouden met de controle van het dataverkeer. Hiervoor hebben we gekozen voor een combinatie van SNMP en RRDtool. Met behulp van SNMP kunnen gebruikers van om het even waar in het netwerk gegevens opvragen over het dataverkeer 56
Besluit dat langs de verschillende ethernetpoorten de router binnenkomt of verlaat. We hebben voor de eenvoud onze router ook als server laten fungeren, zodat de gegevens van SNMP ook in de router zelf verwerkt kunnen worden. RRDtool zal deze gegevens in onze router/server opslaan in een database. Het kan van deze gegevens ook grafieken maken die we met behulp van een webpagina en een Apache webserver over het hele netwerk toegankelijk kunnen maken. Als laatste stap kunnen we met tc het dataverkeer over het netwerk volledig regelen. We kunnen data van bepaalde bronnen een hogere of lagere prioriteit geven, of enkele pc's toegang geven tot een groter deel van de totale bandbreedte over het netwerk. Tc kan je volledig configureren met enkele commando's. Voor dit alles maken we gebruik van vele shellscripts om de installatie en het gebruik van de verschillende programma's, technieken en protocols voor een stuk te vergemakkelijken of te automatiseren. Zo hebben we een script gemaakt dat de volledige testomgeving met alle nodige instellingen en programma's op om het even welk Ubuntusysteem installeert. En ook in de testomgeving zelf maken we vaak gebruik van een shellscript. We hebben bijvoorbeeld een script dat automatisch gegevens opvraagt met SNMP, ze vervolgens toevoegt aan een database en tenslotte de opdracht geeft om verschillende grafieken te genereren voor in de webpagina. Een volledig overzicht van alle scripts die we gebruiken met een bondige uitleg vind je terug in hoofdstuk 6.
7.2 Persoonlijke visie We kunnen stellen dat we erin geslaagd zijn een virtuele omgeving te creëren op basis van User-Mode Linux. We hebben ernaar gestreefd om dit zo gebruiksvriendelijk mogelijk in elkaar te steken. Door alles in verschillende scripts te verwerken stellen we gebruikers in staat om het gehele project op een zeer eenvoudige manier te installeren en op te starten. Hiervoor hoeft hij geen diepgaande kennis te hebben van de achterliggende software. Daarnaast is ons project ook nog eens op zo'n manier opgebouwd dat het eenvoudig toegepast kan worden in echte netwerken. Doordat we voor het hele project enkel gebruik gemaakt hebben van gratis open-sourcesoftware kan iedereen eenvoudig alle nodige programma's van het internet downloaden. We hebben enkel gebruik gemaakt van Linuxvarianten van de software, maar van de meeste programma's zijn ook andere varianten beschikbaar. De principes van onze werkwijze beperken zich dus niet enkel tot het besturingssysteem Linux. Doordat we het hele jaar door zoveel met Linux hebben gewerkt, hebben we hieromtrent veel ervaring kunnen opdoen. We zijn er ons meer en meer bewust van geworden wat de kracht van scripts is in een besturingssysteem dat voornamelijk met commando's werkt. Daarbij komt nog dat User-Mode Linux ons een beter inzicht heeft verschaft in de interne werking van het besturingssysteem Linux. Tot slot kunnen we nog zeggen dat het misschien niet echt mogelijk is om rechtstreeks op dit eindwerk verder te bouwen. We zijn er echter van overtuigd dat de testomgeving die we voor ons project ontworpen hebben een nuttige aanvulling kan zijn voor eventuele toekomstige eindwerken. En ook in de lessen datacommunicatie kunnen studenten nuttig gebruik maken van onze testomgeving om met allerlei programma's en protocols te leren werken.
57
Literatuurlijst [1] Open-sourcesoftware [Wikipedia], online, http://nl.wikipedia.org/wiki/Open-sourcesoftware, 2007-04-13 [2] Emulator [Wikipedia], online, http://nl.wikipedia.org/wiki/Emulatie, 2007-05-01 [3] SLATS, J., Emulatie: Context en huidige stand van zaken, online, www.digitaleduurzaamheid.nl/bibliotheek/docs/white_paper_emulatie_Ned.pdf, 2007-05-01 [4] , online, http://www.dia.uniroma3.it/~compunet/netml/, 2006-11-15 [5] BAUER, M., “Running Network Services under User-Mode Linux, Part 1”, The Linux Journal, november 2006, p. 36-39 [6] BAUER, M., “Running Network Services under User-Mode Linux, Part 2”, The Linux Journal, december 2006, p. 42-46 [7] Simple Network Management Protocol [Wikipedia], online, http://nl.wikipedia.org/wiki/SNMP, 2006-12-20 [8] Simple Network Management Protocol [Wikipedia], online, http://en.wikipedia.org/wiki/SNMP, 2007-02-14 [9] Net-SNMP, online, http://net-snmp.sourceforge.net/, 2007-02-20 [10] VAN DEN BOGAERDT, A., rrd-beginners, online, http://oss.oetiker.ch/rrdtool/tut/rrd-beginners.en.html, 2007-03-07 [11] ROCKWOOD, B., Creating an initial RRD, online, http://www.cuddletech.com/articles/rrd/ar01s02.html, 2007-04-22 [12] VAN DEN BOGAERDT, A., rrdtutorial, online, http://oss.oetiker.ch/rrdtool/tut/rrdtutorial.en.html, 2007-03-13 [13] LILLEY, C., Scalable Vector Graphics (SVG), XML Graphics for the Web, online, http://www.w3.org/Graphics/SVG/, 2007-04-12 [14] BOXMAN, J., A Practical Guide to Linux Traffic Control, online, http://trekweb.com/~jasonb/articles/traffic_shaping/, 2007-04-17 [15] BROWN, M., Traffic Control HOWTO, online, http://tldp.org/HOWTO/Traffic-Control-HOWTO/, 2007-05-16 [16] COHEN, D. en DEVERA, M., HTB Linux queuing discipline manual, user guide, online, http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm, 2007-05-14 [17] HUBERT, B., Linux Advanced Routing & Traffic Control HOWTO, online, http://lartc.org/howto/, 2007-03-29 [18] Shebang [Wikipedia], online, http://en.wikipedia.org/wiki/Shebang, 2007-05-21 [19] Repository [Wikipedia], online, http://en.wikipedia.org/wiki/Repository, 2007-05-22 58
Bijlagen
Inhoudsopgave A DocBook .................................................................................................................................... 3 A.1 Wat is DocBook? ............................................................................................................ 3 A.2 XSL stylesheets ............................................................................................................... 4 A.2.1 Nodige tools ......................................................................................................... 4 A.2.2 Een eigen XSL-stylesheet ..................................................................................... 6 A.2.3 Voorbeeld van een customization layer ................................................................ 7 B Een eigen image creëren .......................................................................................................... 17 B.1 Image voor de client-UML ............................................................................................ 17 B.2 Image voor de router-UML ........................................................................................... 20 B.2.1 Basis-image aanmaken ........................................................................................ 20 B.2.2 Extra programma's installeren ............................................................................. 21 B.2.3 Image verder afwerken ....................................................................................... 23 Literatuurlijst ................................................................................................................................ 24
Bijlage A: DocBook De laatste jaren wordt er meer en meer gebruik gemaakt van online documentatie. Bedrijven kunnen een wereldwijd publiek bereiken door hun documentatie op enkele HTML-pagina's online te zetten. Of ze gebruiken software om bestanden met een mooie opmaak te genereren die dan gedownload en uitgeprint kunnen worden. Een goede standaard die gebruikt kan worden als bron voor alle twee deze toepassingen is DocBook [1].
A.1 Wat is DocBook? DocBook is een markuptaal voor technische documentatie. Oorspronkelijk is DocBook ontworpen als een standaard voor computerdocumentatie, maar het kan voor veel meer gebruikt worden dan enkel dat. Een groot voordeel van DocBook is dat een document geen opmaak bevat, maar enkel inhoudelijke componenten die op een gestructureerde manier worden opgesteld. Er bestaan vele tools die een DocBook-document kunnen omzetten naar een ander, presentatievriendelijk, formaat. Door zo'n tool te gebruiken kan je overzichtelijke bestanden maken met een gewenste opmaak. Voorbeelden van bestanden die je kan genereren zijn HTML, PDF en man pages1. Doordat de opmaak pas achteraf aan een document wordt toegevoegd kan je garanderen dat altijd dezelfde opmaak wordt gebruikt doorheen het gehele document. Zo voorkom je slordige en onsamenhangende documenten. Ook kan je makkelijk verschillende documenten genereren van hetzelfde DocBook-document. Zo kan je dus van jouw document een PDF- en een HTML-bestand maken zonder enige aanpassingen te moeten doen in het bronbestand. Een DocBook-document ziet er als volgt uit: Een eenvoudig boekHoofdstuk 1 <para>Dit is een eerste paragraaf. <para>Meerdere paragrafen zijn uiteraard ook mogelijk. Hoofdstuk 2 <para> Je kan je document zeer eenvoudig in hoofdstukken indelen.
DocBook was in het begin gebaseerd op SGML2, maar de latere versies (vanaf versie 4.1.2 in februari 2001) zijn ook beschikbaar in XML3. Een DocBook XML-bestand wordt haast altijd voorafgegaan door een XML-declaratie en een DTD. 1
Zowat alle op UNIX gebaseerde besturingssystemen maken gebruik van man pages (voluit: manual pages) voor hun documentatie. 2 Standard Generalized Markup Language: een metataal om markuptalen te definiëren 3 eXtensible Markup Language: een algemene en veelgebruikte markuptaal die voortkomt uit SGML
3
DocBook Een XML-declaratie bevat een aantal gegevens over het XML-bestand. Vooral het versienummer is belangrijk om te voorkomen dat het document niet meer geldig zou zijn als de XML-specificties in de toekomst zouden veranderen. Een XML-declaratie voor een DocBook-document ziet er als volgt uit:
Een DTD, of Document Type Declaration, is in principe niet verplicht voor elk XML-bestand, maar in werkelijkheid zullen alle DocBook-documenten wel een DTD hebben. In de DTD staan gegevens over de gebruikte versie van DocBook en wat het rootelement van het document is [3]. Een DocBook-DTD kan er als volgt uitzien:
In het voorbeeld is gekozen voor een online DTD, maar je kan net zo goed een offline DTD ingeven. Voor wie geen verbinding heeft met het internet kan dit een goede oplossing zijn. Een nadeel van een offline DTD is dat je het pad naar je DTD mogelijk moet aanpassen elke keer iemand anders je document wilt gebruiken en valideren. Merk ook op dat in voorafgaand voorbeeld gebruik gemaakt werd van book als rootelement. Er zijn echter ook andere rootelementen mogelijk. Voor artikels kan je bijvoorbeeld best gebruik maken van een DTD met rootelement article. DocBook-documenten zijn in de eerste plaats bedoeld om door een machine verwerkt te worden en omgezet te worden naar een ander formaat, maar ze zijn simpel in opmaak en structuur zodat ze ook door de mens goed leesbaar zijn. Je kan dus een DocBook-document maken met niets anders dan een gewone teksteditor. Om het de auteur iets makkelijker te maken bestaan er echter ook vele hulpmiddelen die helpen bij het structureren en valideren van een DocBook-document. Zo zijn er bijvoorbeeld speciale editors die aan de hand van de DTD helpen om de juiste structuur van een document uit te werken.
A.2 XSL stylesheets Eens je een DocBook XML-bestand geschreven hebt wil je het uiteraard omvormen naar een formaat dat beter geschikt is om af te drukken of te lezen, zoals HTML of PDF. Doordat een XML-bestand geen opmaak bevat moet deze dus nog worden toegevoegd. Dit doe je door het samen met een XSL-bestand (Extensible Stylesheet Language) te verwerken.
A.2.1 Nodige tools Voordat je een DocBook-document kan omvormen moet je in de eerste plaats zorgen dat het gevalideerd is. Validatie gebeurt door een XML-validator. Deze gaat kijken naar de DTD van een XML-bestand en kan zo nagaan of het bestand voldoet aan de standaard. Sommige teksteditors hebben een ingebouwde XML-validator, zodat je je bestanden niet meer apart moet valideren. In de teksteditor JEdit, bijvoorbeeld, kan je een plug-in installeren die je XML-bestanden automatisch valideert bij het opslaan. Een Document dat niet voldoet aan de eisen die de DTD stelt kan niet of niet juist omgevormd worden. 4
DocBook Vervolgens heb je een XSL-stylesheet nodig dat je document van de nodige structuur en opmaak voorziet. Je kan de officiële 'DocBook XSL stylesheets', gemaakt door Norman Walsh, downloaden van http://docbook.sourceforge.net/ of je kan een online stylesheet gebruiken. Als deze stylesheets niet voldoen aan jouw eisen en normen kan je ze ook zelf aanpassen. De XSL-stylesheets van DocBook zijn zo ontworpen dat iemand met een beetje ervaring met XSL ze eenvoudig kan aanpassen. Hierop gaat sectie A.2.2 nog wat dieper in. Als je DTD en je stylesheet in orde zijn kan je beginnen met het omvormen van je documenten. Om XML om te zetten is er in de eerste plaats een XSL-processor nodig. Dit stukje software zal een XML-bestand omzetten naar een formaat met opmaak. Er zijn drie verschillende standaarden die een XSL-processor kan gebruiken [2]. Een eerste standaard is XPath (XML Path Language). Deze standaard kan worden gebruikt om een bepaald onderdeel van een XML-bestand te behandelen en een verschillende opmaak toe te passen op deze verschillende onderdelen. Elke XSL-processor gebruikt deze standaard. Een tweede standaard is XSLT (XSL Transformations). Deze standaard zet XML-bestanden om in andere XML-formaten (zoals FO), HTML of gewone tekst. Dit kan gebruikt worden om inhoud te herschikken of nieuwe inhoud bij te voegen. Een derde en laatste standaard is XSL-FO (XSL Formatting Objects), ook wel eens gewoon XSL genoemd. Deze doet beroep op de andere twee om een bestand om te zetten naar een ander formaat, zoals een PDF-bestand. Deze bestanden bevatten de inhoud van het originele bestand, maar hebben ook een eigen unieke opmaak. Je kan ze zo online zetten of uitprinten. Een voorbeeld van een XSLT-processor is xsltproc. Dit is een zeer snelle en bovendien gratis processor, geschreven in C door Daniel Veillard. Meer uitleg over xsltproc kan je vinden op de website http://xmlsoft.org/XSLT/. Xsltproc zit standaard in de meeste op UNIX gebaseerde besturingssystemen. Twee andere XSLT-processors die je geheel gratis kan verkrijgen zijn Saxon (http://saxon.sourceforge.net/) en Xalan (http://xml.apache.org/xalan-j/). Deze zijn alle twee in Java geschreven, maar ze zijn iets trager dan xsltproc. Voor dit document hebben we gebruik gemaakt van xsltproc als XSLT-processor. De omzetting kan in Linux met één enkel commando gebeuren: xsltproc --noout 1 \ --output fo-files/docbook.fo \ 2 --stringparam use.extensions 0 \ 3 --stringparam fop1.extensions 1 \ 4 docbook2fo.xsl \ 5 docbook.xml 6 1 2 3
4
5 6
Deze parameter onderdrukt de standaard output die anders in het consolevenster getoond wordt. Je kan eenvoudig bepalen hoe het uitgangsbestand moet heten en waar xsltproc het moet plaatsen. De parameter use.extensions moet op 0 gezet worden omdat xsltproc geen Java stylesheet extensions kan gebruiken. Hier wordt een parameter meegegeven die ervoor zorgt dat de output van xsltproc beter geschikt is om verder te verwerken met Apache FOP (hierover meer in de volgende alinea's). Hier wordt het XSL-stylesheet met de opmaak meegegeven. Tenslotte moet je ook nog het bronbestand meegeven. Hier wordt een DocBook-document in XML-formaat als bron gebruikt. 5
DocBook Naast een XSLT-processor heb je ook een XSL-FO-processor nodig. Een voorbeeld hiervan is FOP (Formatting Objects Processor). Dit is een processor van het Apache XML Project die gebaseerd is op Java en die gratis te verkrijgen is op http://xml.apache.org/fop/. FOP is nog steeds in ontwikkeling en heeft nog enkele beperkingen, maar het kan reeds dienen om FO om te zetten naar PDF. Uiteindelijk is het de bedoeling dat FOP gebruikt kan worden voor de omzetting naar veel meer formaten dan enkel PDF. Enkele andere gratis XSL-FO-processors zijn xmlroff (http://xmlroff.sourceforge.net/) en PassiveTeX (http://www.tei-c.org.uk/Software/passivetex/). Voor dit document hebben we gebruik gemaakt van Apache FOP als XSL-FO-processor. Ook FOP kan met één eenvoudig commando een document omzetten: fop docbook.fo 1 docbook.pdf 2 1
2
Als eerste parameter moet je het ingangsbestand meegeven. Hier is dat het FO-bestand dat eerst door xsltproc gegenereerd is. Met een tweede parameter kan je een bestandsnaam opgeven voor je uitgangsbestand.
Als je met xsltproc in combinatie met Apache FOP werkt moet je er op letten dat je de juiste versie van FOP gebruikt. Als je een nieuwere versie dan 0.20.5 gebruikt is er geen probleem. Voor versies 0.20.5 en ouder moet je in xsltproc de parameter --stringparam fop.extensions 1 meegeven in de plaats van --stringparam fop1.extensions 1. Om het gebruik van deze twee commando's te vergemakkelijken kan je een shellscript of een makefile maken die ze alle twee automatisch achter elkaar uitvoert. Op deze manier moet je de commando's niet iedere keer volledig opnieuw intypen.
A.2.2 Een eigen XSL-stylesheet Zoals sectie A.2.1 reeds vermeldt, zijn de DocBook XSL-stylesheets zo ontworpen dat je ze met een beetje kennis van XSL makkelijk kan aanpassen. Om te voorkomen dat je je aanpassingen in de originele stylesheets moet doorvoeren kan je ook gebruik maken van een customization layer. Dit is een laag boven het originele stylesheet waar enkel je aanpassingen in staan. Voor de andere opmaakeigenschappen wordt dan gewoon doorverwezen naar de originele stylesheets, die nog onveranderd zijn. Het gebruik van een customization layer voor je aanpassingen heeft enkele belangrijke voordelen [2]. Een eerste voordeel is dat je een customization layer kan toepassen op verschillende versies van de DocBook XSL-stylesheets. Als je dus besluit om over te gaan naar een nieuwere versie van de stylesheets, dan kan je dezelfde customization layer blijven gebruiken. Als je daarentegen alle aanpassingen in de stylesheets zelf doorgevoerd hebt, dan moet je alle aanpassingen in de nieuwe versie weer opnieuw doorvoeren. Een tweede voordeel is dat het een stuk makkelijker is om je aanpassingen te delen met andere DocBook-gebruikers. Je hoeft enkel je customization layer door te sturen in plaats van een volledige set stylesheets. Aangezien de originele stylesheets uit een vrij groot aantal verschillende XSL-bestanden bestaat kan dit wel een groot voordeel zijn. Een derde voordeel is dat de aanpassingen die je gedaan hebt volledig gescheiden zijn van de originele stylesheets. als je dus bijvoorbeeld een fout maakt in je aanpassingen en je weet niet meer hoe je deze fout terug kan rechtzetten, dan kan je je customization layer gewoon terug verwijderen. Nu kan je de originele stylesheets terug gebruiken of een nieuwe customization layer aanmaken. Als je je customization layer niet zomaar wilt verwijderen kan je ook hulp vragen aan iemand die er meer van 6
DocBook weet. Je hoeft in dit geval maar één bestand door te sturen waarmee deze persoon je hele configuratie kan bekijken en eventueel ook corrigeren. Om ervoor te zorgen dat de opmaak op het volledige document wordt toegepast en niet alleen op de objecten die je in een customization layer hebt aangepast moet je een verwijzing naar het originele DocBook XSL-stylesheet in je customization layer bijvoegen. Dit doe je met een import. Voor alle elementen waarvan je de opmaak niet hebt aangepast in je customization layer wordt gewoon de standaard opmaak gebruikt. Een import van de originele stylesheets van Norman Walsh ziet er als volgt uit: <xsl:import href="/.../fo/docbook.xsl"/>
Je kan ook een verwijzing naar een online versie van de standaard DocBook XSL-stylesheets in je customization layer invoegen in plaats van een verwijzing naar een offline versie. Dit heeft als voordeel dat het pad dan voor iedereen hetzelfde is. Dit is vooral handig als je je stylesheet met andere gebruikers deelt. Een nadeel van een online stylesheet is dat er bij elke transformatie een aanzienlijke hoeveelheid data gedownload moet worden van het internet. Verdere instructies over welke aanpassingen je allemaal kan doorvoeren in de XSL-stylesheets en hoe je dit juist moet doen vallen buiten het bestek van dit werk. Meer informatie hierover kan je terugvinden op de website http://www.docbook.org/ of in het boek DocBook XSL: The Complete Guide door Bob Stayton.
A.2.3 Voorbeeld van een customization layer Voor de volledigheid vind je hieronder de customization layer met de opmaakeigenschappen van dit document. Deze customization layer houdt zoveel mogelijk rekening met de BIN-normen. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version='1.0'> <xsl:import href="stylesheets/1.72.0/fo/docbook.xsl"/> <xsl:include href="titlepage-template.xsl"/>
Om dit titelsjabloon te kunnen gebruiken moet het eerst getransformeerd worden door een XSLT-processor. Hierbij moet je het stylesheet titlepage.xsl van de standaard XSL-stylesheets gebruiken. Als je xsltproc gebruikt kan je transformeren met het commando: xsltproc --noout \ --output titelsjabloon.xsl \ /.../template/titlepage.xsl \ titelsjabloon.xml
16
Bijlage B: Een eigen image creëren Deze bijlage legt de procedure uit om een eigen image te maken. Omdat we twee verschillende systemen willen emuleren die elk een ander doel hebben, maken we in ons eindwerk ook gebruik van twee verschillende images. De werkwijze voor het aanmaken van deze images is hetzelfde, alleen is er bij de router-image wat extra software nodig. Een eerste deel bespreekt stap voor stap hoe je een image voor de client-UML kan maken. Omdat deze UML maar zeer eenvoudig hoeft te zijn, kunnen we de grootte van het bestand beperken. Een volgend deel behandelt vervolgens de procedure voor de router-image.
B.1 Image voor de client-UML Als eerste stap maak je een bestand met een grootte van 180 MB. Dit is groot genoeg voor een zeer eenvoudig besturingssysteem. Het bestand, dat we hier de naam Debian-root_fs geven, zal na het aanmaken enkel gevuld zijn met nullen. De naam verwijst naar het besturingssysteem dat we achteraf gaan installeren in het image-bestand. Omdat je geen besturingssysteem kan installeren in een image met enkel nullen is het nodig dat je deze image eerst formatteert, zodat het een eigen bestandssysteem krijgt. We hebben gekozen voor het ext31-bestandssysteem, maar afhankelijk van de Linuxdistributie kan je ook andere bestandssystemen gebruiken. dd if=/dev/zero of=Debian-root_fs bs=1 count=1 seek=180M sudo mkfs -t ext3 -F Debian-root_fs
Om het Debian-besturingssysteem te kunnen installeren binnen een besturingssysteem dat reeds geboot is, moet je de image eerst mounten. Vervolgens kan je de installatie uitvoeren via debootstrap [4]. Debootstrap is standaard geïnstalleerd in Debian of Ubuntu. We opteren om de laatste versie van Debian, etch genoemd, te gebruiken voor onze image. Debootstrap downloadt de benodigde broncode en pakketten van een Debian-server die je meegeeft aan het commando. Omdat je alles downloadt zal de tijd om Debian te installeren grotendeels afhankelijk zijn van de downloadsnelheid. Deze manier van werken omzeilt de gebruikelijke installatie van Linux. Bij een gebruikelijke installatie boot je haast altijd van een CD of DVD. Hierdoor benut je de mogelijkheden van de hardware niet optimaal. Pas na dat een besturingssysteem volledig opgestart is maakt het goed gebruik van alle mogelijke hardware. Een installatie via debootstrap zal dus een pak sneller verlopen, aangezien het vanaf het begin gebruik kan maken van de volledige hardware [5]. sudo mkdir /mnt/image sudo mount -o loop Debian-root_fs /mnt/image sudo debootstrap --arch i386 etch /mnt/image \ http://http.us.debian.org/debian
Als je nu aanpassingen wil doorvoeren in het nieuwe besturingssysteem zonder het zelf te booten kan je je huidig besturingssysteem laten geloven dat het geboot is met de zopas aangemaakte image als bestandsysteem. Hiervoor moet je de root-map van je besturingssysteem tijdelijk veranderen naar de map waarin je je image gemount hebt. De root-map van het besturingssysteem veranderen kan je doen met het commando chroot. Hierdoor heeft je besturingssysteem tijdelijk geen toegang meer tot de 1
ext3 of het third extended filesystem is een veelgebruikt journaling filesystem bij het besturingssysteem Linux. Een journaling filesystem is een bestandssysteem dat veranderingen tijdelijk in het geheugen bijhoudt, in plaats van ze onmiddellijk weg te schrijven naar het bestandssysteem op de harde schijf.
17
Een eigen image creëren mappen die zich boven de nieuwe root-map bevinden. In figuur B.1 zie je schematisch wat chroot met de root-map van het besturingssysteem doet. sudo chroot /mnt/image
Figuur B.1: Schema van een chroot-omgeving Als je in de chroot-omgeving zit kan je een update doen van alle beschikbare pakketten van het nieuwe besturingssysteem. Vervolgens installeer je alle extra pakketten die het besturingssysteem nodig zal hebben. Zoals eerder reeds vermeld heeft de client-UML haast geen extra software nodig. Om wat makkelijker te kunnen werken in de testomgeving waarvan de UML deel uit zal maken, is het pakket 'psmisc' misschien wel handig. Dit pakket bevat tools die de processen kunnen tonen en eventueel beëindigen. apt-get update apt-get install psmisc
Omdat het hier gaat om een image voor User-Mode Linux, die gestart zal worden via de commandolijn, moet je vervolgens nog een aantal belangrijke stappen doorlopen. Als eerste moet je fstab aanpassen. Dit is het configuratiebestand waar het besturingssysteem uit leest welke partities het moet mounten en naar welke map. pico -w /etc/fstab
Voor User-Mode Linux raden we de volgende fstab aan: proc /dev/ubda none
/proc / /mnt/host
proc ext3 hostfs
defaults defaults /mnt/uml,defaults
0 0 1
0 1 1
De laatste regel van fstab zegt dat User-Mode Linux automatisch een map van de host-pc gaat mounten binnen de client-UML. Hiervoor gebruikt het het virtuele bestandssysteem hostfs. Dit bestandssysteem 18
Een eigen image creëren zorgt ervoor dat je vanuit de UML toegang krijgt tot de bestanden die zich binnen de map op de host bevinden. Omdat je de map /mnt/uml/ van de host wil mounten naar de map /mnt/host/ van de UML moet je deze map nog aanmaken in het image-bestand. mkdir /mnt/host
Om netwerk in orde te krijgen hebben we het script init.sh geschreven. In hoofdstuk 6 kan je zien wat dit script allemaal doet. De UML moet het script uitvoeren bij het booten. De enige manier om dit te doen is het script toevoegen aan rc.local. Dit is een bestand dat altijd op het einde van het opstarten van de host-pc gelezen wordt. Voeg de regel /mnt/host/init/init.sh toe vlak boven exit 0 omdat met dit laatste het bestand verlaten wordt. pico -w /etc/rc.local
In een volgende stap moet je de gegevens in verband met de runlevels aanpassen. Als je de image boot zonder de volgende aanpassingen door te voeren zal elk runlevel van Debian in een apart xterm-venster2 starten. De runlevels van Debian zijn [6]: • Runlevel 0: Halt System (het systeem stilleggen) • Runlevel 1: Single user mode • Runlevel 2-5: Multi user mode with Graphical User Interface (GUI) • Runlevel 6: Reboot System (het systeem herstarten) Het eerste runlevel wordt enkel gebruikt om te debuggen en dus niet voor de normale werking van het Linuxsysteem. Runlevels twee tot en met vijf laten gebruikers toe in grafische omgeving te werken. Om te voorkomen dat User-Mode Linux voor elke UML zes verschillende vensters opent, moet je ervoor zorgen dat slechts een van de runlevels gestart kan worden. Hiervoor moet je enkel het configuratiebestand inittab aanpassen [7]. pico -w /etc/inittab
Zet in inittab de volgende regels in commentaar: #1:2345:respawn:/sbin/getty 38400 tty1 #2:23:respawn:/sbin/getty 38400 tty2 #3:23:respawn:/sbin/getty 38400 tty3 #4:23:respawn:/sbin/getty 38400 tty4 #5:23:respawn:/sbin/getty 38400 tty5 #6:23:respawn:/sbin/getty 38400 tty6
En voeg de volgende regel vervolgens toe aan het einde van innittab. Deze regel maakt één enkel runlevel aan, dat de originele runlevels vervangt. c0:1235:respawn:/sbin/getty 38400 tty0 linux 2
Xterm is een terminal die gebruik maakt van de GUI van Linux.
19
Een eigen image creëren Deze regel geeft ook aan dat User-Mode Linux tty0 gebruikt als apparaat om de gebruikers in te loggen. Je moet dus ook zorgen dat de gebruikersnaam en het paswoord via dit apparaat geverifieerd kunnen worden. Het is alleen maar mogelijk als het apparaat voorkomt in het bestand securetty. Dit is standaard niet het geval. Je moet tty0 dus toevoegen in de lijst van apparaten. pico -w /etc/securetty
Op dit moment zijn de voorbereidingen van de image afgerond. We raden nog aan om de pakketten die apt-get heeft afgehaald te verwijderen alvorens de chroot-omgeving te verlaten. Dit zal een aantal megabytes vrijmaken. apt-get clean exit
Je kan de image al eens testen door deze te starten. Dit doe je door een UML te starten, zoals hoofdstuk 3 aantoont. We geven het commando voor de duidelijkheid hier nog eens. In deze commando's is linux een link naar de UML-kernel. Alvorens de image op te starten is het zeer belangrijk dat je de image eerst unmount! sudo umount /mnt/image ln -s ${HOME}/GFproject/linux-2.6.20.1/linux linux ./linux root=/dev/ubda ubd0=Debian-root_fs
B.2 Image voor de router-UML Een tweede onderdeel van deze bijlage leert hoe je een image kan maken voor de router-UML. Deze UML heeft meer software nodig en zal dus logischer wijze ook een groter image-bestand moeten hebben dan de client-UML. Voor deze tweede image moet je hetzelfde principe volgen als in het eerste deel. Stappen die overeenkomen met het vorige gedeelte worden hier dan ook niet meer in detail uitgelegd.
B.2.1 Basis-image aanmaken Omdat de router-UML meer software nodig heeft dan de client-UML's heb je ook een groter image-bestand nodig. Maak bijvoorbeeld een bestand van 330 MB en vul het weer met nullen, zoals in het vorige deel. Ook hier is het ext3-bestandssysteem een goede keuze om te formatteren. Mount de image weer naar /mnt/image en installeer Debian op dezelfde manier als hiervoor beschreven. dd if=/dev/zero of=Debian-router_fs bs=1 count=1 seek=330M sudo mkfs -t ext3 -F Debian-router_fs sudo mount -o loop Debian-router_fs /mnt/image sudo debootstrap --arch i386 etch /mnt/image \ http://http.us.debian.org/debian
Als je je image gemount hebt kan je met behulp van chroot de software van de image aanpassen. Zorg er eerst met env -update voor dat de omgevingsvariabelen in de chroot-omgeving in orde zijn. Daarna kan je beginnen met de installatie van een eerste pakket, build-essential. Dit pakket voorziet een volledige C-compiler met alle nodige bibliotheken. Vervolgens heb je ook het pakket apache nodig, omdat je hiermee de grafieken op een webpagina wil publiceren. Verder installeer je nog libart-2.*. Dit wil 20
Een eigen image creëren zeggen dat je alle pakketten installeert die iets met libart-2 te maken hebben (libart-2.0-2, libart-2.0-dev en pkg-config). Tenslotte installeer je nog de pakketten psmisc en iproute. Psmisc bevat de tools om de draaiende processen binnen een systeem te kunnen zien en om deze eventueel stil te leggen. Iproute bevat dan weer de nodige tools om traffic control te kunnen controleren. sudo chroot /mnt/image env -update apt-get update apt-get install build-essential apt-get install apache apt-get install libart-2.* apt-get install psmisc iproute
Vervolgens moet je de bestanden fstab, rc.local, inittab en securetty weer aanpassen op exact dezelfde manier als bij de client-UML. Het enige verschil met de aanpassingen bij de client-UML is dat je nu de regel /mnt/host/init_router/init.sh moet toevoegen in rc.local. pico pico pico pico
Als dit in orde is kan je de tijdelijke bestanden van apt-get verwijderen en de chroot-omgeving verlaten. apt-get clean exit
B.2.2 Extra programma's installeren De router heeft, naast de basissoftware, ook nog extra software nodig. hiervoor moet je enkele archieven afhalen van de officiële website van de pakketten. • zlib-1.2.3.tar.gz: http://www.zlib.net/ • libart_lgpl-2.3.17.tar.gz: http://packages.debian.org/stable/source/libart-lgpl • libpng-1.2.10.tar.gz: http://www.libpng.org/ • freetype-2.1.10.tar.bz2: http://www.freetype.org/ • rrdtool-1.2.19.tar.gz: http://oss.oetiker.ch/rrdtool/ • net-snmp-5.4.tar.gz: http://net-snmp.sourceforge.net/ De gedownloade software pak je vervolgens tijdelijk uit in de root-map van de image. De optie -C geeft aan naar waar je de archieven wil uitpakken. sudo sudo sudo sudo
Een eigen image creëren sudo tar -xvzf rrdtool-1.2.19.tar.gz -C /mnt/image/root/ sudo tar -xvzf net-snmp-5.4.tar.gz -C /mnt/image/root/
In een volgende stap moet je de extra software installeren. Dit moet je weer in de chroot-omgeving doen. Vervolgens ga je naar de map waarin je de pakketten hebt uitgepakt. sudo chroot /mnt/image cd root
Nu kan je de verschillende pakketten installeren. Aan het einde van elke installatie kan je de map waarin je de pakketten hebt uitgepakt gewoon verwijderen.
SNMP 5.4 cd net-snmp-5.4/ ./configure make && make install
Om de communcatie op punt te stellen moet je een gebruikersgroep aanmaken. Voor een toepassing in de testomgeving is een gebruiker met enkel leesrechten voldoende. Vervolgens zorg je ervoor dat de UML de SNMP-deamon start op het einde van het bootproces. Hiervoor voeg je het startcommando /usr/local/sbin/snmpd toe aan rc.local. echo 'rocommunity gf' > /usr/local/share/snmp/snmpd.conf cd .. rm -r net-snmp-5.4/
zlib 1.2.3 cd zlib-1.2.3/ ./configure make && make install cd .. rm -r zlib-1.2.3/
libart 2.3.17 cd libart_lgpl-2.3.17/ ./configure make && make install cd .. rm -r libar_lgpl-2.3.17/
libpng 1.2.10 cd libpng-1.2.10/ cp scripts/makefile.linux Makefile make && make install
22
Een eigen image creëren cd .. rm -r libpng-1.2.10/
FreeType 2.1.10 cd freetype-2.1.10/ ./configure && make && make install cd .. rm -r freetype-2.1.10/
RRDtool 1.2.19 tzconfig cd rrdtool-1.2.19 BUILD_DIR=/tmp/rrdbuild INSTALL_DIR=/usr/local/rrdtool-1.2.19 mkdir -p $BUILD_DIR ./configure - -prefix=$INSTALL_DIR make && make install cd .. rm -r rrdtool-1.2.19/
B.2.3 Image verder afwerken Als alle software geïnstalleerd is kan je nog wat extra aanpassingen doen in de image. Om het opstarten van het hele project te vergemakkelijken kan je bijvoorbeeld nog een alias aanmaken. Deze alias voeg je toe vóór de regel msg n in het bestand .profile in de root-map. pico -w .profile
De alias gf zorgt ervoor dat je automatisch in de juiste map terechtkomt en dat de UML het opstartscript uitvoert. alias gf='cd /mnt/host/uml && ./rrdtool.sh'
Indien alles gelukt is kan je vervolgens chroot-omgeving weer verlaten met exit. Bij deze is de zelf gemaakte router-image volledig klaar. Je kan hem, net zoals de client-UML, weer uittesten met het volgende commando. Let er weer op dat je je image eerst unmount, om problemen te vermijden. sudo umount /mnt/image/ ./linux root=/dev/ubda ubd0=Debian-router_fs
23
Literatuurlijst [1] WALSH, N. en MUELLNER, L., DocBook: The Definitive Guide, O'Reilly, 1999 [2] STAYTON, B., DocBook XSL: The Complete Guide, Third Edition, Sagehill Enterprises, Santa Cruz CA, 2005 [3] WALSH, N., The Source for Documentation, online, http://www.docbook.org/, 2007-04-05 [4] MCFARLAND, P., How to make a UML image on Debian, online, http://adterrasperaspera.com/blog/2007/02/13/how-to-make-a-uml-image-on-debian/, 2007-05-14 [5] GALÁN, F. en MONREAL, M., How to create a VNUML-compatible root filesystem from scratch using debootstrap, online, http://www.dit.upm.es/vnumlwiki/index.php/Create-rootfs, 2007-05-14 [6] Runlevel [Wikipedia], online, http://en.wikipedia.org/wiki/Runlevel, 2007-05-18 [7] OCAÑA GONZÁLEZ, E., Making usermode linux work, online, http://blogs.igalia.com/eocanha/?p=14, 2007-05-15