Internet Service Dämonen |
Übersicht |
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 Dämon inetd |
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
daytime
discard
echo
time
»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.
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
Sockettyp
Protokoll
[no]wait
Benutzerkennung
Dienstname
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.
Der Dämon xinetd |
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.
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
type
flags
socket_type
protocol
wait
user
group
instances
nice
server
server_args
only_from
no_access
access_times
log_type
log_on_success
log_on_failure
rpc_version
env
passenv
port
redirect
bind
banner
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)
SIGUSR2 (12)
SIGQUIT (3)
SIGTERM (15)
SIGHUP (1)
SIGIO (29)
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 } |