[Zurück] [Home] [Weiter]       http://rowa.giso.de  

Eine frei verwendbare Unix-Grundlagenschulung mit muLinux

Aktivieren des Webservers PYGMY

Was macht ein Web-Server?

Ein Web-Server ist ein Programm, das auf einer Maschine im Netz nistet und auf einen Web-Browser wartet, der eine Anfrage übermittelt, üblicherweise wegen einer Datei.

Server und Browser kommunizieren mit Hilfe des HyperText Transfer Protocol (HTTP), einer besonderen Sprache, die speziell für die Übermittlung von Hypertext-Dokumenten durch das Web entwickelt wurde. Daher werden Web-Server häufig auch HTTPD-Server genannt.

Das D steht für Daemon. Wie wir wissen ist ein Daemon ein Programm, das im Hintergrund hockt und auf Anfragen wartet. Erhält er eine Anfrage, so wacht er auf, bearbeitet die Anforderung und legt sich dann wieder schlafen.

Sendet ein Server eine Datei so fügt er einige Angaben hinzu, welche Art von Datei er sendet (beispielsweise eine GIF-Datei). So kann der Browser erkennen, ob er sie selbst lesen kann oder dafür ein Hilfsprogramm (Plug-In) starten muß. Dazu sendet der HTTPD-Server zwei Zeilen vor der eigentlichen Datei als Header (engl. für Kopf). Die erste Zeile gibt den sogenannten MIME-Type an. Die zweite Zeile ist leer. MIME bedeutet Multipurpose Internet Mail Extensions. Das ist ein Standard zum Beschreiben von Dateien. Früher wurde diese vor allem für die Klassifizierung von an Emails angehangenen Dateien verwendet. So konnte das Mail-Programm erkennen welche Dateiart vorliegt und das entsprechende Programm zur Darstellung dieser Datei starten. Heute wird dieser Standard von vielen Internetdiensten genutzt.

Man kann das Verhalten des Servers auch insofern erweitern, daß er auch Dateien verschickt, die nicht Teil des normalen Satzes sind. Schließlich können Web-Server auch so eingerichtet werden, daß sie Skripts und Programme aufrufen, die auf Angaben basieren, die der Surfer mit Hilfe seines Browser eingibt. Diese speziellen Programme werden Gateway-Programme oder Gateway-Skripts genannt. Die Spezifikationen dazu Common Gateway Interface (CGI). Programmiersprachen für CGI sind Perl, das im HTML-Code eingebundene PHP, Java und Shell-Scripte.

Der Standard Webserver ist Apache www.apache.org (wird Äpätchie gesprochen). Dieser Ausdruck kommt von "a patchy server". Apache wurde aus dem NCSA-Webserver und einer Reihe von Patch-Dateien (Patch = engl. für Flicken) aufgebaut. Apache ist wie Linux open source und damit kostenlos. Er ist nicht nur für alle Unix-Versionen verfügbar, sondern auch für Windows. Apache läuft oft auf Solaris, FreeBSD und natürlich auf Linux. Man verwendet in der Internettechnik das Kunstwort LAMP für die Beschreibung der Standardtechnologieen. L steht für Linux, A für Apache, M für die das Datenbanksystem MySQL und P für das oben erwähnte PHP. MySQL und PHP sind ebenfalls open source. Normale Webserver lassen sich also vollkommen mit kostenloser Software betreiben.

Auf der muLinux Diskette befindet sich der minimalistisch Webserver PYGMY. Bevor wir diesen aktivieren schauen wir ihn uns etwas genauer an. Wir wollen wissen wo sich pygmy befindet und was für eine Datei das ist. Dies konnen wir mit einer Befehlszeile tun. Der in den zurück zeigenden Hochkommas eingebundene Befehl wird ausgeführt und das Ergebnis von dem davor stehenden Programm ausgewertet.

/# file `wich pygmy`
/usr/sbin/pygmy: script text
/# _

Es also eine Script-Datei, die wir uns gleich mal ansehen.

/# cat usr/sbin/pygmy
#!/bin/ash

while [ 1 ]
do
/usr/bin/nc -v -e /usr/sbin/in.pygmy -l -p 80 2>>/var/log/httpd.log
done
/# _

Die erste Zeile kennzeichnet diese Datei als Shell-Script und es wird dazu die Shell /bin/ash gestartet. Die Befehle while, do und done bilden eine Programm-Schleife, die immer wieder durchlaufen wird. Dadurch wird das in dieser Schleife eingeschlossene Programm ständig am Leben gehalten.

Das Programm nc ist die Abkürzung für NetCat, ein Netzwerk-Client mit minimal gehaltener Funktionalität. Man kann damit sowohl TCP-Verbindungen zu beliebigen Ports aufbauen als auch UDP-Verbindungen "vortäuschen" (faken). Er eignet sich zudem dazu, bestimmte Ports abzuhören. Wir schauen uns mal seine Parameter an.

/# nc -h
[V1.10]
connect to somewhere:   nc [-options] hostname port[s] [ports] ...
listen for inbound:     nc -l -p port [-options] [hostname] [port]
options:
        -e prog             program to exec after connect [dangerous!!]
        -g gateway          source-routing hop point[s], up to 8
        -G num              source-routing pointer: 4, 8, 12, ...
        -h                  this cruft
        -i secs             delay interval for lines sent, ports scanned
        -l                  listen mode, for inbound connects
        -n                  numeric-only IP addresses, no DNS
        -o file             hex dump of traffic
        -p port             local port number
        -r                  randomize local and remote ports
        -s addr             local source address
        -t                  answer TELNET negotiation
        -u                  UDP mode
        -v                  verbose [use twice to be more verbose]
        -w secs             timeout for connects and final net reads
        -z                  zero-I/O mode [used for scanning]
port numbers can be individual or ranges: lo-hi [inclusive]
/# _

In dem PYGMY-Script werden folgende Optionen verwendet:
-v Verbose (engl. für geschwätzig) gibt Meldungen aus.
-e /usr/sbin/in.pygmy Führt nach Kontaktaufnahme das nachfolgende Programm aus.
-l Hört (engl. listen) auf eingehende Anfragen.
-p 80 Abgehört wird Port 80, also das WWW-Port.
2>>/var/log/httpd.log Fehlermeldungen werden an die Log-Datei angefügt.

Also hört hier NetCat am Port 80 und führt bei Anfragen das hinter -e erwähnte Porgramm aus. Dies ist gefährlich (engl. dangerous), da man mit nc leicht ein Trojanisches Pferd programmieren kann. Die Logdatei /var/log/httpd.log zeichnet alle Fehlermeldungen auf und wird erst nach dem Aktivieren von PYGMY angelegt.

/# ls /var/log
identd.log
/# _

Noch ist also keine httpd.log vorhanden. Schauen wir uns mal das Programm /usr/sbin/in.pygmy an.

/# less /usr/sbin/in.pygmy

Na hier steht ja schon etwas mehr drin. Natürlich lassen wir uns davon nicht beeindrucken. Wie wir aus dem Kapitel "Einfache Shell-Scripte" wissen, ist das Doppelkreuz # der Beginn eines Kommentars. In der ersten Zeile steht ein besonderer Kommentar, der das aufzurufende Programm definiert. Hier ist das /bin/ash. Zu Beginn werden Variablen zur allgemeinen Konfiguration definiert. Ein guter Programmierstil legt die Definitionen am Anfang des Programms fest. So lassen sich Änderungen leichter durchführen. Man muß dann nicht erst den gesamten Quelltext (engl. source code) durchsuchen.

        SED=sed
        ROOT=/home/httpd
        LOGO=/tmp/httpd.logo
        LOGFILE=/var/log/httpd.log

Die Variable SED definiert das Programm zum stapelweisen Verarbeiten von Texten. Hier ist das der Stream Editor sed. Das klingt sehr beeindruckend. Wir werden uns erst später mit diesem Programm beschäftigen. ROOT definiert das Heimatverzeichnis des Webservers. Dort, bzw. in Unterverzeichnissen liegen die HTML-Dateien und Grafiken. Dies wollen wir überprüfen. Dazu wechseln wir zur zweiten Konsole und loggen uns ein.

[Alt] [F2]

/# ls /home/httpd
total 5
0 doc        0 images       2 linux.html
0 download   3 index.html
/# _

Hier befinden sich wirklich HTML-Dateien. Man erkennt sie an der Endung .html. HTML-Dateien sind Textdateien, die HTML-Befehle enthalten. Diese Befehle werden in spitzen Klammern < > eingeschlossen. Web-Browser verstehen diesen Code mehr oder weniger gut und stellen uns diese Dateien als WWW-Seiten dar. Wer will kann ja mal sich eine solche Datei mit less index.html anschauen. Die Datei index.html ist eine besondere Datei in jedem Verzeichnis. Der Web-Server liefert diese Datei, wenn bei der Anfrage keine Datei sondern nur ein Verzeichnis angegeben wurde.

Doch zurück zur ersten Konsole und damit zur Datei in.pygmy.

[Alt] [F1]

Die nächsten Variablen definieren ein Logo für den Server und die Log-Datei. Bei der Log-Datei wissen wir, daß sie noch nicht angelegt wurde. Doch wie ist das mit dem Logo? Wir testen dies in der zweiten Konsole.

[Alt] [F2]

/# ls /tmp

Da ist keine Datei httpd.logo. Diese wird erst im nachfolgenden Code von /usr/sbin/in.pygmy erstellt. Dazu wechseln wir wieder in die erste Konsole und blättern im Text nach unten.

[Alt] [F1]

[Cursor nach unten]

Unter den Hilfsfunktionen (engl. auxiliary funtion) sehen wir den Code zur Erzeugung des Logos.

# auxiliary functions

cat > $LOGO <<END
<hr>
<font size=-1> <i>
<center>
powered by PYGMY -- muLinux rustic WWW server, on <b>`hostname` </b>
</center>
</i></font>
</html>
END

Mit dem Befehl cat wird der nachfolgende Text bis zum END in die Logo-Datei geschrieben. Das heißt, bei der ersten WWW-Anfrage wird die Logo-Datei angelegt. Wir erkennen hier die HTML-Befehle an den spitzen Klammern. Wir werden uns später im Kapitel "Erstellen einer kleinen Website" damit beschäftigen. Das Logo wird bei Meldungen des Webservers ausgegeben.

Nach dem Programmabschnitt zur Erzeugung des Logos erfolgen einige Funktionsdefinitionen. Funktionen werden bei den meisten Programmiersprachen verwendet. Das sind Programmbausteine, die immer wieder benötigt werden. Vor dem ersten Aufruf müssen sie erst definiert werden. Dies erfolgt beim Shell-Script wie bei vielen Sprachen.

funktionsname()
{
   Befehl
   Befehl
   ...
}

Zuerst wird der Funktionsname festgelegt. Mit diesem Namen wird die Funktion später aufgerufen. Dann kommen runde Klammern. Diese dienen bei Bedarf zur Parameterübergabe. Unser Webserver-Programm hat dazu bei keiner Funktion den Bedarf. Zwischen geschweiften Klammern werden dann die in dieser Funktion abzuarbeitenden Befehle geschrieben. Schauen wir und dazu weiter unseren kleinen Webserver an.

# Explorer requires explicitily a standard header
send_header()
{
cat <<END
HTTP/1.0 200 OK
Date: `date`
Server: Pygmy/Mulinux (Rustic) WWW server, v`cat /etc/version`
   Leerzeile
END
}

Die Funktion send_header() sendet beim Aufruf den Header. Die erfolgt wieder mit dem Befehl cat der alles bis zu END ausgibt. Es wird die hier verwendete Version des HTTP ausgegeben und die Meldung "200 OK". Das heißt die angeforderte Datei ist vorhanden und wird anschließend gesendet. Danach wird das Datum und Informationen zum Server dargestellt. Wichtig ist die abschließende Leerzeile. So erkennt der WWW-Browser das Ende des Headers. Was danach kommt ist die angeforderte Datei.

build_error()
{
cat > /tmp/pyg_error.html << END
<html>
<h1>PYGMY (pygmean) www server</h1>
<hr>
<b>Not Found</b>
<p>
The requested URL $1 was not found on this server.
`cat $LOGO`
END

echo /tmp/pyg_error.html

}

Wenn eine angeforderte Datei auf dem Server nicht vorhanden ist, muß eine entsprechende Fehlermeldung gesendet werden. Dafür ist die Funktion build_error() zuständig. Dazu wird mit dem Befehl cat die Datei /tmp/pyg_error.html angelegt mit dem nachfolgenden HTML-Code gefüllt. Dazu gehört auch das Server-Logo. Anschließend wird die Datei mit echo ausgegeben.

build_dir()
{
case "$1" in
*/)
        base="."
        ;;
*)
        base="`basename $1`"
        ;;
esac

/bin/ls -s1 $1 | fgrep -v "total" > /tmp/raw.list

        parent=`dirname $base`

cat > /tmp/html.list <<END
<html>
<h1>Index of $1</h1>
<hr>
<p>
<a href="../"> Parent directory </a> <p>
END


cat /tmp/raw.list | \
$SED "s/ *\([0-9]\+\) *\(.\+\)/\
\<a href=$base\/\2\>    \2 \
\<\/a\> \1k\<p\>/g" >>/tmp/html.list

cat $LOGO >> /tmp/html.list
echo /tmp/html.list
}

Die Funktion build_dir() wird aufgerufen, wenn ein Verzeichnis angefordert wird, indem sich keine Datei index.html oder index.htm befindet. Ist dies der Fall, so wird der Inhalt des Verzeichnisses aufgelistet. Dazu wird der Stream Editor sed verwendet. Dessen Syntax möchte ich hier aber noch nicht erklären. Kommen wir zu wichtigsten Funktion. Das ist die Funktion GET(). Diese Funktion wird bei Anfragen an den Server aufgerufen. Die Anfrage nach einer Datei erfolgt in HTTP mit dem Befehl GET. Deshalb wurde diese Funktion hier so benannt. Sie hätte allerdings auch Pflaumenkuchen() heißen können. Der HTTP-Befehl GET übergibt als Parameter den Namen der Datei. Die Übergabe des ersten Parameter erolgt im Script-Programm mit $1. In der ersten Zeile wird $1 in die Variable page geschrieben.

GET()
{
page=$1

Mit Hilfe der Befehlskombination case (engl. für Fall) ... esac (case rückwärts geschrieben) können Fallunterscheidungen gemacht werden. Hier wird getestet ob am Anfang des Parameters ein Slash / steht. Wenn ja, dann sei die Variable pre leer, wenn nicht, dann sei pre gleich "/". Dann kommt die gleiche Fallunterscheidung für ein mögliches Slash am Ende. Hier wird post entsprechend gesetzt. Dies ist notwendig um jeweils ein Slash als Trennzeichen entsprechend der Unixschreibweise zu erhalten.

# / problem
case "$page" in
/*)
        pre=""
        ;;
*)        pre="/"
        ;;
esac

case "$page" in
*/)
        post=""
        ;;
*)      post="/"
        ;;
esac

Mit Hilfe der Befehlskombination if (engl. für wenn), then (engl. für dann), else (engl. für ansonsten) und fi (if rückwärts) können Entscheidungen getroffen werden. Das heißt: "Wenn etwas richtig ist dann mache das. Ansonsten mache jenes." Hier wird erst getestet ob ein Verzeichnis angefordert wurde. Wenn dies so ist wird versucht entweder die Datei index.htm oder index.html zu finden und mit dem kompletten Pfad zu senden. Ist weder index.htm oder index.html vorhanden so wird mit die Funktion build_dir aufgerufen, die das den Inhalt des Verzeichnisses auflistet. Wenn kein Verzeichnis angefordert wurde, so wird wohl eine Datei gemeint sein und die Variable PAGE mit dem Dateinamen und dem kompletten Pfad gefüllt.

# if a dir? exist index.html?

PAGE=

if [ -d $ROOT$pre$page ] ; then

[ -f $ROOT${pre}${page}${post}index.htm ] \
&& PAGE=$ROOT${pre}${page}${post}index.htm

[ -f $ROOT${pre}${page}${post}index.html ] \
&& PAGE=$ROOT${pre}${page}${post}index.html

[ -z "$PAGE" ] && PAGE=`build_dir $ROOT$sep$page`

else
        PAGE=$ROOT$pre$page         # is a file
fi

Jetzt wird getestet ob die Datei oder das Verzeichnis vorhanden ist. Wenn nicht wird mit build_error eine Fehlermeldung erzeugt.

# exist ?

if [ ! -f "$PAGE" ] ; then
        PAGE=`build_error $PAGE`
fi

Ist alles OK wird mit send_header der Header und danach mit cat die Datei ausgegeben.

# Ok, send page

send_header
cat $PAGE

}

Das waren soweit die Funktionen. Jetzt kommt das kurze Hauptprogramm (engl. main). Das Hauptprogramm wird mit while do ... done am Leben gehalten. Mit read wird die WWW-Browseranfrage gelesen. Danach erfolgt ein Eintrag in der Log-Datei. Mit if wird getestet ob es wirklich eine GET-Anforderung ist. Wenn ja wird die Funktion GET aufgerufen. Wenn nicht ertönt ein akustisches Signal und es wird eine Fehlermeldung ausgegeben.

# Main

while [ 1 ]
do

read x
echo " got [$x]" >> $LOGFILE
set -- $x

if [ "$1" = GET ] ; then
        GET $2
else
        [ "`which wave`" ] && wave -c 800 2
        send_header
        echo "<html> Error: $1 unknown. </html>"
fi
exit
done

Ich hoffe es war nicht zuviel Script-Programmierung auf einmal. Wir werden uns später mit der Script-Programmierung beschäftigen. Wer also hier nicht jedes Detail verstanden hat, braucht deshalb keine großen Sorgen machen. Hauptsache wir haben jetzt eine grobe Vorstellung was ein Webserver mindestens zu tun hat.

Aktivieren des Webservers

Wir wollen jetzt unseren Webserver zum Leben erwecken. Vorher testen wir aber ob nicht vielleicht doch schon ein Port offen ist.

/# nmap localhost
Scanning ports (hosts localhost), wait ...
localhost [127.0.0.1] 113 (auth) open

Nur das Port 113 ist offen. Wir öffnen jetzt Port 80.

/# setup -f httpd
Setting httpd up: ask_the_user

                    - Internal Web Server -

Depending of what addons are mounted, muLinux support
some httpd daemon, running on port 80:

        - Pygmy: the rustic script-based web-server
        - thttpd: the fast web-server, developed by Jef Poskanzer



Do you want a running webserver?: Y

Wir wir sehen gibt es auf einer Add-on-Diskette noch einen zweiten Webserver mit dem Namen thttpd. Dieser ist schon eher ein richtiger Webserver. Wir begnügen uns hier aber mit PYGMY.

Starting PYGMY (rystic) web-server ... 1517

Der Webserver wird gestartet und die Prozessnummer ausgegeben. Diese ist bei Euch sicher anders als hier. Wir testen ob PYGMY läuft.

/# ps aux | grep pygmy
    ...             /usr/sbin/pygmy

Er läuft. Ist das Port auch offen?

/# nmap localhost
Scanning ports (hosts localhost), wait ...
localhost [127.0.0.1] 113 (auth) open
localhost [127.0.0.1] 80  (www) open

Es ist offen. Wäre unser Rechner an das Internet angeschlossen, hätten wir ein großes Sicherheitsloch. PYGMY ist nämlich nicht sehr sicher. Wurde auch eine Log-Datei erzeugt?

/# ls /var/log
httpd.log identd.log
/# _

Na klar! Schauen wir doch mal rein.

/# cat /var/log/httpd.log
connect to [127.0.0.1] from localhost [127.0.0.1] 4194
 got[]
listening on [any] 80 ...
/# _

Testen mit dem WWW-Browser quark

Wir testen ob wir mit dem WWW-Browser Kontakt zum WWW-Server aufnehmen können.

/# quark http://localhost

 [r]eload [g]o [b]ack [v]iew [u]rls [s]ave [d]ownload [P]rint [q]uit    [h]elp 

                    Welcome to PYGMY (pygmean) WWW server!
 ----------------------------------------------------------------------------

 This is a placeholder page installed by the muLinux setup scripts,
 because no home page was installed on this host. You may want to replace
 this as soon as possible with your own web pages, of course....

 PYGMY is a small HTTP server, implemented with a shell script
 (2174 bytes) and netcat port scanner. PYGMY run via /etc/inittab
 and support: images, download and directory browsing. Remember: images
 are fetched one by one, pressing RELOAD button in your browser.
 Ehmm: the image is on the X11 addon ... :(

 http://localhost                                                   Quark v.xx
 cursor up/down, pag up/down to move                       vxx, hyperlink mode

Scheint alles zu funktionieren. Der Server zeigt uns eine Begrüßungsseite, die einige Informationen zum Server bietet. Erst im nächsten Kapitel lernen wir quark genauer kennen. Wir lernen hier nur einen Befehl kennen:

q

Mit Q verlassen wir den Browser wieder. Mit der Befehlswiederholung rufen wir nochmals quark auf. Diesmal geben wir noch den Port 80 an.

/# quark http://localhost:80

Das Ergebnis ist das Gleiche. Port 80 ist das Standardport für WWW und braucht nicht extra angegeben zu werden. Man kann aber auch den WWW-Server auf einen anderen Port betrieben. So können z. B. mehrere WWW-Server auf einen Rechner laufen. Wir probieren nach dem Verlassen von quark noch eine Variante.

/# quark http://localhost:80/index.html

Auch hier haben wir das gleiche Ergebnis. Wir haben ja in dem Script gesehen, daß der Webserver index.html ergänzt, wenn nur ein Verzeichnis angegeben wurde. Wir schauen uns nochmal die Log-Datei an.

/# cat /var/log/httpd.log
connect to [127.0.0.1] from localhost [127.0.0.1] 4194
 got[]
listening on [any] 80 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 4687
 got [GET]
listening on [any] 80 ...
/# _

Er hat unsere Anforderung registriert. Und noch ein Versuch. Wir geben jetzt der Funktion zur Ausgabe der Fehlermeldung eine Chance.

/# quark http://localhost/quatsch

Der WWW-Server zeigt uns seine Fehlerseite.

/# cat /var/log/httpd.log
connect to [127.0.0.1] from localhost [127.0.0.1] 4194
 got[]
listening on [any] 80 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 4687
 got [GET]
listening on [any] 80 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 4687
 got [GET /quatsch]
/# _

Hier wird also genau registriert ob man Quatsch macht. Jetzt versuchen wir zu hacken indem wir zwei Verzeichnisse höher auslesen wollen.

/# quark http://localhost/../../

Entgegen aller Sicherheitsregeln bei Server können wir höher als das HTTPD-Root-Verzeichnis gehen. Wir können uns so jede Datei herunterladen. So z. B.

/# quark http://localhost/../../etc/passwd

Eine Freude für jeden Systemadministrator. Dieser WWW-Server ist also nur zum Test oder für Schulungen geeignet. PYGMY hat noch einen weiteren Nachteil. Er kann pro GET-Anforderung nur eine Datei senden. Meist besteht aber gehören zu einer HTML-Datei noch weitere Dateien, wie z. B. Grafiken. Diese könnten dann nur über ein Reload beim Browser geladen werden.

[Zurück] [Home] [Weiter]