Anfang
Inhalt
Einleitung
Erste Schritte
Die Bash
Das Dateisystem
Nutzerkommandos
Installation
Shells
Unix-Werkzeuge
System-Administration
X Window System
Der Kernel
Netzwerk Grundlagen
Geschichte
Protokolle
Netzwerkstruktur
Allgemeine Dienste
Konfigurationsdateien
Konfigurationstools
Diagnose
Internet Service
Dämon
Remote Procedure Call
Request For Comments
Netzwerk Clients
Netzwerk Server
Netzwerk Sicherheit
Anhang
Register |
Damit ein Client einen entsprechenden Server findet, benötigt er neben Kenntnis der IP-Adresse des
Serverrechners auch noch die Portnummer, an der der Dienst wartet.
In den ersten Unix-Systemen mit TCP/IP-Unterstützung wurden bereits während des Systemstarts
sämtliche Serverprozesse aktiviert, die ihre Ports initialisierten und auf eintreffende Anforderungen
warteten. Traf ein Verbindungswunsch ein, erzeugte ein Server einen Kindprozess, vererbte diesem die
geöffnete Verbindung, schloss seinerseits die Verbindung und begab sich selbst erneut in den
Wartezustand, um eintreffende Anfragen entgegenzunehmen.
Bald erkannte man, dass die meisten Serverprozesse vollkommen umsonst gestartet wurden, sie wurden im
Laufe der Aktivität des Systems nicht oder nur selten in Anspruch genommen. Mit den von den warteten
Prozessen in Anspruch genommenen CPU-Zeiten konnte man noch gut leben, denn da sie nichts zu erledigen
hatten, erzeugten sie auch nur geringe Rechenlast, aber der ständig reservierte Hauptspeicher, zumal in
jenen Zeiten die heutigen RAM-Dimensionen ins Reich der Fantasie gehörten, entpuppte sich bald als
Schwachpunkt.
Die Lösung kam, wie so viele Anreize aus jenen Tagen, aus Berkeley und wurde mit dem inetd als
erstem »Superserver« mit 4.3BSD veröfentlicht.
Anstelle der Aktivierung sämtlicher Netzwerkdienste wurde nun nur noch der Superserver beim Start des
Systems zum Leben erweckt. Dieser entnahm alle zu eröffnenden Portnummern einer Konfigurationsdatei und
überwachte diese auf eintreffende Verbindungsanforderungen. Lag irgendwo eine Anfrage an, startete der
Superserver den entsprechenden Serverdienst und vermachte ihm die bereits offene Verbindung.
Als Konsequenz hieraus ist die meiste Zeit über stets nur ein Server aktiv und alle weiteren
können bei Bedarf nachgeladen und nach Erfüllung der Anforderung auch wieder beendet werden.
Der inetd ist der Standard-Superserver für Linux, jedoch lässt er in Sachen
Zugriffssteuerung viele Wünsche offen. So hat sich der xinitd in vergangenen Jahren zu einer
ernsthaften Alternative entwickelt.
Der inetd ist der mit Abstand beliebteste Superdämon. Er ist in der Lage sowohl TCP- als auch
UDP-basierte und in aktuellen Versionen sogar RPC-Dienste zu starten. Dazu
überwacht er die Ports (oft wird in diesem Zusammenhang auch von Internet Sockets gesprochen) der ihm
anvertrauten Server und entscheidet anhand der Portnummer, an der eine Anforderung eintrifft, welcher
Netzwerkdienst zu starten ist.
Nicht alle Dienste, die der Rechner im Netzwerk anbieten soll, werden von einem Superserver verwaltet.
Einige hochverfügbare Server wird man schon während des Systemstarts aktivieren, man denke nur
einen http-Dämonen auf einem frequentierten Webserver. Für welche Dienste sich der inetd
letztlich verantwortlich zeichnet, muss ihm deshalb in seiner Konfigurationsdatei /etc/inetd.conf
mitgeteilt werden.
Es gibt Dienste, die sind in ihrer Art so einfach, dass es vergebene Mühe wäre, sie in ein
eigenes Programm zu packen. Der inetd verfügt deswegen über einige interne Dienste, deren
Anforderung er höchst persönlich erfüllt:
chargen |
|
Der »Zeichengenerator«. Trifft ein Verbindungswunsch für diesen Dienst ein, wird
mit einem ununterbrochenen Zeichenstrom geantwortet, solange, bis der Client die Verbindung beendet.
Der Service kann zur Performance-Messung eingesetzt werden. |
daytime |
|
Gibt die Rechnerzeit in einem für den Mensch verständlichen Format wieder |
discard |
|
Der Dienst basiert auf dem Initial Connection Protocol und anwortet bei eintreffendem
Verbindungswunsch mit dem Aufbau einer Verbindung in die Gegenrichtung. Anschließend wartet
discard auf eine Anwort und leitet diese nach /dev/null. Ist die Anwort »verarbeitet«,
beendet sich der Prozess. Der Dienst wird zu Testzwecken eingesetzt. |
echo |
|
Der Dienst sendet die empfangenen Daten unverändert an den Absender zurück. |
time |
|
Gibt die Rechnerzeit in einem maschinenlesbaren Format wieder |
»time« und »daytime« werden bei einem Zeitserver
benötigt, die anderen Dienste sollten nur temporär für Testzwecke geöffnet werden, da sie
von außen zum Erzeugen unnötiger Rechenlast missbraucht werden können.
Die Datei /etc/inetd.conf
Alle Dienste, die der inetd starten soll, müssen in dessen Konfigurationsdatei /etc/inetd.conf
aufgeführt sein. Beginnt eine Zeile mit dem Doppelkreuz, so handelt es sich um einen Kommentar, alle
anderen Zeilen bestehen aus 6 Feldern:
Dienstbezeichnung |
|
Name des Serverdienstes, so wie er in der Datei /etc/services
eingetragen ist. Im Falle eines RPC-Dienstes muss zusätzlich dessen Versionsnummer angegeben
werden. Der RPC-Dienstname steht in der Datei /etc/rpc, ein gültiger Eintrag lautet dann
<RPC-Dienst>/<Version>. |
Sockettyp |
|
Die Art des Sockets muss hier angegeben werden. Als Schlüsselwörter sind zulässig:
stream, dgram, raw, rdm und seqpacket. stream ist dabei ein
Socket, in dem ein Datenfluss (»streaming«) eintrifft, so wie sie das Transportprotokoll
TCP implementiert. dgram ist der »Telegrammtyp« und korrespondiert mit dem
UDP-Protokoll. raw sind Rohdaten, also Daten, die nicht in einemTransportprotokoll verpackt
sind; sie werden direkt an die Anwendung weitergereicht. rdm (reliably delivered message) sind
»sicher verteilte« Daten, so dass in den oberen Schichten des TCP-Protokollstacks von ihrer
Unversehrtheit ausgegangen werden kann. seqpacket ist eine Sequenz von Paketen. |
Protokoll |
|
Ist der Name des Protokolls, über den der Dienst arbeitet, in den meisten Fällen wird es
sich um tcp oder udp handeln. Im Falle eines RPC-Dienste steht hier z.B. »rpc/tcp« oder
»rpc/udp«. |
[no]wait |
|
Eines der Schlüsselworte ist immer anzugegen, wobei die Angabe sich einzig auf das
UDP-Protokoll auswirkt. wait bewirkt, dass der inetd nach dem Verbindungsaufbau neue
Anforderungen erst entgegennimmt, wenn der UDP-Dienst seine Arbeit beendet hat. Mit nowait wird
unverzüglich auf neue Anforderungen gewartet. |
Benutzerkennung |
|
Name des Benutzers, in dessen Auftrag der Dienst gestartet wird. |
Dienstname |
|
Vollständiger Programmname des Dienstes (inklusive Pfad und Optionen). |
Eine Datei »/etc/inetd.conf« könnte dann wir folgt aussehen (Auszüge):
user@sonne> cat /etc/inetd.conf
# <service_name> <sock_type> <proto> <flags> <user>
<server_path> <args>
#
# echo stream tcp nowait root internal
# echo dgram udp wait root
internal
# discard stream tcp nowait
root internal
# discard dgram udp
wait root internal
daytime stream tcp nowait
root internal
daytime dgram udp
wait root internal
# chargen stream
tcp nowait root internal
# chargen dgram udp
wait root internal
time stream tcp nowait root
internal
time dgram udp wait
root internal
#
# These are standard services.
#
# ftp stream tcp nowait root
/usr/sbin/tcpd wu.ftpd -a
ftp stream tcp nowait root
/usr/sbin/tcpd in.ftpd
#
# If you want telnetd not to "keep-alives" (e.g. if it runs over a ISDN
# uplink), add "-n". See 'man telnetd' for more deatails.
telnet stream tcp nowait root
/usr/sbin/tcpd in.telnetd
nntp stream tcp nowait news
/usr/sbin/tcpd /usr/sbin/leafnode
smtp stream tcp nowait root
/usr/sbin/sendmail sendmail -bs
# printer stream
tcp nowait root /usr/sbin/tcpd /usr/bin/lpd -i
# Shell, login, exec and talk are BSD protocols.
# The option "-h" permits ``.rhosts'' files for the superuser. Please look at
# man-page of rlogind and rshd to see more configuration possibilities about
# .rhosts files.
# shell stream tcp nowait root /usr/sbin/tcpd in.rshd -L
# shell stream tcp nowait root
/usr/sbin/tcpd in.rshd -aL
#
login stream tcp nowait root
/usr/sbin/tcpd in.rlogind
# login stream tcp nowait
root /usr/sbin/tcpd in.rlogind -a
# exec stream tcp nowait root
/usr/sbin/tcpd in.rexecd
talk dgram udp wait
root /usr/sbin/tcpd in.talkd
ntalk dgram udp wait
root /usr/sbin/tcpd in.talkd
finger stream tcp nowait nobody /usr/sbin/tcpd
in.fingerd -w
# systat stream
tcp nowait nobody /usr/sbin/tcpd /bin/ps -auwwx
# netstat stream tcp nowait
root /usr/sbin/tcpd /bin/netstat
# identd is now started at boot time, the following is not longer necessary.
# ident stream tcp wait nobody
/usr/sbin/in.identd in.identd -w -e
# swat is the Samba Web Administration Tool
swat stream tcp nowait.400
root /usr/sbin/swat swat
|
Der einigen Diensten vorgeschaltete TCP-Wrapper »/usr/sbin/tcpd« implementiert eine dedizierte
Zugangskontrolle für den jeweiligen Netzwerkdienst. Er ist eine relevante Komponente der
Netzwerksicherheit und wird im Kapitel Netzwerk-Sicherheit TCP-Wrapper
vorgestellt.
Im vergangenen Abschnitt lernten Sie den inetd kennen. Die Bemerkungen zur nichtvorhandenen
Zugangskontrolle sollten Ihnen ebenso wenig entgangen sein, wie der Kompromiss des TCP-Wrappers, der die
Sicherheitsmängel des inetd teilweise beheben kann. Dennoch kann die Vorgehensweise des
»alles ist erlaubt, solange es nicht explizit verboten wurde« bei halbherziger Konfiguration
schnell zu unbemerkten Sicherheitslöchern führen.
Der xinetd ist ein vollwertiger Ersatz für den inetd. Das »x« deutet hier
nicht etwa ein X-Window-Programm an, sondern steht für »extended« (erweitert). Er
implementiert dieselben internen Dienste wie der »inetd« (chargen, daytime, discard, echo, time).
Des Weiteren ermöglicht der xinetd die Protokollierung aller Zugriffe.
Die Datei /etc/xinetd.conf
Konfiguriert wird der xinetd mittels der Datei /etc/xinetd.conf. Er kennt zwei Typen von
Einträgen. Zum einen handelt es sich um den optionalen »default«-Eintrag, der auf alle
anderen Einträge angewandt wird, insofern diese die Optionen nicht selbst definieren. Dieser
default-Eintrag besitzt folgende Struktur:
default
{
<Schlüssel><Operator><Parameter><Parameter>...
...
} |
Die weiteren Einträge betreffen die einzelnen Dienste:
service <Dienstbezeichnung>
{
<Schlüssel><Operator><Parameter><Parameter>...
...
} |
Als Operatoren sind zulässig: die normale Zuweisung mit »=«, das Hinzufügen
eines weiteren Schlüssels mit »+=« und das Entfernen eines Schlüssels mit
»-=«. Die Verwendung der Operatoren »+=« und »-=« macht vor allem
in Verbindung mit dem »default«-Eintrag Sinn.
Von den nachfolgend beschriebenen Schlüsseln sind im Falle des default-Eintrags nicht alle sinnvoll.
Erlaubt sind hier »log_type«, »log_on_success«, »log_on_failure«,
»only_from«, »no_access«, »passenv«, »instances« und
»disabled«. »disabled« kann nur im »default«-Eintrag stehen und sperrt
den Zugang zu den angegebenen Diensten.
id |
|
Jeder Dienst muss eindeutig identifiziert werden können, die Angabe ist für
Mulit-Protokoll-Dienste notwendig. Fehlt sie, so wird der Name des Dienstes
(»Dienstbezeichnung«) als ID angenommen. |
type |
|
Kombination aus »RPC« (RPC-Dienst), »INTERNAL« (interner Dienst) oder
»UNLISTED« (Dienst, der nicht in den Dateien »/etc/rpc« oder
»/etc/services« eingetragen ist). |
flags |
|
Von den möglichen Einträgen ist »IDONLY« der Interessanteste. Eine
Anforderung wird dann nur zugelassen, wenn der entfernte Benutzer identifiziert werden kann. |
socket_type |
|
Die Typen sind »stream«, »dgram«, »raw« und
»seqpacket« und besitzen dieselbe Bedeutung wie beim inetd beschrieben wurde. |
protocol |
|
Name des Protokolls, über das der Dienst arbeitet. Fehlt die Angabe, wird das
»übliche« Protokoll des Dienstes angenommen. |
wait |
|
Steht hier »yes«, wartet der xinitd nach einem Verbindungsaufbau auf das Ende
des Servers, bevor er neue Anforderungen entgegen nimmt. Mit »no«, startet er ggf. weitere
Serverprozesse. |
user |
|
Die Nutzerkennung, unter der der Serverprozess gestartet wird. |
group |
|
Die Gruppenkennung, unter der der Serverprozess gestartet wird. |
instances |
|
Maximal mögliche Anzahl Prozesse, die den Dienst zu einer Zeit ausführen dürfen.
Neben der Zahl darf auch »UNLIMITED« stehen. |
nice |
|
Priorität des Serverprozesses. |
server |
|
Programmname des Servers (inklusive Pfad) |
server_args |
|
Argumente des Serverprogrammes |
only_from |
|
Liste von Rechnern, von denen der Zugang erlaubt ist. Die Angabe kann eine IP-Adresse, ein
Rechnername, eine Netzwerkadresse oder ein Adressbereich sein (192.168.100.12/100 erlaubt den Zugriff
von den Rechner 192.168.100.12 bis 192.168.100.100) |
no_access |
|
Rechner, denen der Zugriff verwehrt wird. Die Angaben erfolgen wie unter »only_from«,
wobei bei Mehrfachnennung die »bessere« Übereinstimmung gilt (wurde der Zugriff den
Rechern eines Netzwerks erlaubt und ist nun ein konkreter Rechner aus jedem Netzwerk in der verbotenen
Liste enthalten, so wird ihm der Zugang verwehrt). |
access_times |
|
Tageszeit, zu der der Zugriff erlaubt ist |
log_type |
|
Wo und wie soll protokolliert werden? Mit »SYSLOG Herkunft [Level]« wird die
Protokollierung an den syslogd weitergereicht; mit »FILE Datei
[soft_limit [hardlimit]]« erfolgt sie in der angegebenen Datei. Die beiden Limits sind die
Schranken, wie größ eine Datei maximal werden kann, somit wird ein Volllaufen des
Dateisystems ausgeschlossen. |
log_on_success |
|
Was wird protokolliert, falls der Server erfolgreich startet? Mögliche Einträge sind:
Prozessnummer des Servers »PID«, Rechnername, von dem die Anforderung kam
»HOST«, Benutzernummer, von dem die Anforderung kam »USERID«, der Exit-Status
des Servers »EXIT« und die Dauer des Serverlaufs »DURATION«. |
log_on_failure |
|
Was wird protokolliert, falls der Server nicht gestartet werden konnte? Neben »HOST«
und »USERID« (wie oben) sind möglich »ATTEMPT«, das die Tatsache des
fehlgeschlagenen Starts notiert und »RECORD«, das weiterführende Informationen (sofern
ermittelbar) vom entfernten Aufruf protokolliert. |
rpc_version |
|
Versionsnummer des RPC-Dienstes |
env |
|
Hier lassen sich zu einem Server zusätzliche Umgebungsvariablen angeben |
passenv |
|
Liste der Umgebungsvariablen, die der xinetd dem Server vererbt |
port |
|
Portnummer, an der der Server wartet, diese muss mit dem Eintrag in der Datei /etc/services (soweit
vorhanden) übereinstimmen |
redirect |
|
Eine Anforderung wird an den angegebenen Rechner weitergeleitet. Dies ist nur bei TCP-Diensten
möglich |
bind |
|
Bindet einen Dienst an ein spezielles Device. So kann z.B. bei einem Rechner mit zwei
Netzwerkkarten sicher gestellt werden, dass der Dienst nur über die eine Karte zugänglich
ist |
banner |
|
Enthält einen Dateinamen, deren Inhalt auf dem zugreifenden Rechner angezeigt wird, falls ihm
der Zugang verwehrt wird. |
Bevor wir uns den Beispielen zuwenden, sind noch einige Anwendungen zu den vom xinetd akzeptierten
Signalen notwendig. Bislang konnten Sie nahezu jeden Prozess mit dem Signal SIGHUP (1) zum erneuten Einlesen
seiner Konfigurationsdateien bewegen. Im Falle des xinetd erreichen Sie damit allerdings nur, dass
dieser sich mit einem Speicherabzug verabschiedet. Aus Sicherheitsgründen reagiert der xinetd auf
einige Signale anders als gewohnt:
SIGUSR1 (10) |
|
Einlesen der Konfigurationsdatei. Aktive Dienste bleiben aktiv. |
SIGUSR2 (12) |
|
Einlesen der Konfigurationsdatei. Aktive Dienste werden sofort beendet. |
SIGQUIT (3) |
|
Programmende, ohne laufende Dienste zu beenden |
SIGTERM (15) |
|
Programmende, laufende Dienste werden zuvor beendet |
SIGHUP (1) |
|
Anlegen eines Speicherauszugs und Programmende |
SIGIO (29) |
|
Interne Konsitenzprüfung des xinetd |
Beispiel 1: Mit dem default-Eintrag spezifizieren wir einige Voreinstellungen, die für alle
Dienste gelten, in denen sie nicht explizit überschrieben werden.
default
{
log_type = FILE /var/lo/xinetd.log
log_on_success = HOST
log_on_failure = HOST USERID
instance = 5
disabled = finger
} |
Beispiel 2: »telnet« soll nur von Rechnern des
Netzwerkes 192.168.100 möglich sein, wobei die Rechner mit den Endnummern 56-192 ausgenommen werden
sollen. Alle fehlgeschlagenen Kontaktversuche sollen über den Syslog-Mechanismus protokolliert werden,
wobei die Herkunft den Sicherheitdiensten (auth) zugeordnet werden soll und die Meldung das Level
»Warnung« erhält:
service telnet
{
socket_type = stream
protocol = tcp
wait = no
user = root
server = /usr/sbin/in.telnetd
only_from = 192.168.100.0
no_access = 192.158.100.56/192
flags = IDONLY
log_on_failure += RECORD
log_type = SYSLOG auth warn
} |
Beispiel 3: »ftp« soll nur in den Nachtstunden erlaubt sein. Gleichzeitig werden 4
Zugriffe zugelassen.
service ftp
{
socket_type = stream
wait = no
user = root
server = /usr/sbin/wu.ftpd
server_flags = -a
log_on_success += DURATION
access_times = 20:00-06:00
instance = 4
} |
Beispiel 4: Von den internen Diensten soll »time« sowohl über »udp«
als auch über »tcp« bereitgestellt werden:
service time
{
id = time_dgram
socket_type = dgram
wait = no
user = root
}
service time
{
id = time_stream
socket_type = stream
wait = no
user = root
} |
Beispiel 5: Zuletzt noch ein Beispiel zu einem RPC-Dienst:
service rstatd
{
type = RPC
socket_type = dgram
wait = yes
user = root
server = /usr/etc/rpc.rstatd
rpc_version = 2-4
env =
LD_LIBRARY_PATH=/etc/securelib
} |
|
|