Dieser Artikel ist größtenteils für alle Ubuntu-Versionen gültig.
Ein inetd, auch Internet-Superserver genannt, verwaltet die Netzwerkverbindungen bestimmter Dienste. Je nach Konfiguration öffnet der Inetd verschiedene Ports und wartet auf Verbindungsanfragen. Erst wenn eine Anfrage eintrifft, wird der betreffende Serverprozess gestartet und seine Ein- und Ausgabe mit dem Datenstrom verknüpft.
Das hat mehrere Vorteile:
Es läuft nur ein Server ständig im Hintergrund, anstatt mehrere verschiedene nur selten benutzte.
Es ist geradezu trivial, einen eigenen Serverdienst zu programmieren. Man braucht sich nicht um Sockets, etc. zu kümmern, sondern benutzt einfach die Standardein- und -ausgabe.
Man kann das tcpd-Paket benutzen, um auf einfache Art mächtige Zugriffskontrollen zu implementieren.
Leider gibt es auch ein paar Nachteile:
Bei jeder neuen Verbindung den Serverdienst neu zu starten kostet Ressourcen.
Man kann nicht jeden beliebigen regulären Serverdienst über den Inetd betreiben, da diese in der Regel eigene Netzwerk-Sockets öffnen (was fehlschlägt, wenn der Port schon vom Inetd belegt ist).
Daraus ergeben sich folgende Konsequenzen:
Der Inetd eignet sich besonders für kleinere, eher selten benutzte Dienste, z.B. Konfigurations-Weboberflächen. Für stark ausgelastete Web- oder Mailserver ist er denkbar ungeeignet.
Serverdienste sind meistens entweder für den alleinstehenden Betrieb oder für den Betrieb mit Inetd ausgelegt und müssen dann dementsprechend verwendet werden. Einige Server, bei denen das sinnvoll ist, wie z.B. diverse FTP-Server, lassen sich durch eine Konfigurationsoption auf beide Arten einsetzen (aber nicht gleichzeitig).
Der Original-Inetd stammte aus einer alten BSD-Version. Inzwischen gibt es aber zahlreiche Neuimplementierungen von anderen Leuten oder Projekten, von denen mehrere in den Ubuntu-Paketquellen vorhanden sind. Es braucht also nur eines der folgenden Pakete installiert zu werden [1]:
netkit-inetd (universe)
openbsd-inetd (main)
inetutils-inetd (universe)
Folgendes Paket ist optional, aber empfohlen:
tcpd (Zugriffsbeschränkungen über TCP-Wrappers s.u. )
mit apturl
Paketliste zum Kopieren:
sudo apt-get install tcpd
sudo aptitude install tcpd
Die meisten Inetds unterscheiden sich nur unter der Haube und benutzen dieselbe Konfigurationsdatei /etc/inetd.conf. Es gibt deswegen wohl nur in den seltensten Fällen Grund dazu, einen anderen zu wählen, als die Ubuntu-Entwickler für den main-Zweig ausgewählt haben. Bis einschließlich Edgy Eft war dies der netkit-inetd, ab Feisty Fawn wurde auf den openbsd-inetd umgestellt.
Etwas anders verhält es sich mit dem Abkömmling xinetd, der tatsächlich einige mächtigere Fähigkeiten besitzt als die traditionellen Vertreter dieses Genres. Diese Vorteile werden jedoch mit einer abweichenden Syntax der Konfiguration erkauft, die mehr Optionen bietet und dafür etwas komplexer ist. Die folgenden Informationen beziehen sich jetzt erstmal auf herkömmliche Inetds. Des Weiteren sei auf den Artikel xinetd verwiesen.
Die Konfiguration des Inetd geschieht über die Datei /etc/inetd.conf. Jede Zeile in dieser Datei beschreibt einen Service. Leerzeilen und solche, die mit einem # beginnen, werden ignoriert. Nach jeder Änderung an dieser Datei muss der Inetd neugestartet werden [4], z.B. so [2]:
sudo /etc/init.d/openbsd-inetd restart
Viele Dienste, die den Inetd benötigen, tragen bei der Installation selber eine passende Zeile in die Datei /etc/inetd.conf ein. Sollte das einmal nicht der Fall sein, oder wenn man einen eigenen Service installieren will, muss man dies mit Hilfe eines Texteditors und Root-Rechten selber erledigen [4]. Dabei besteht jede Zeile aus sieben Spalten, die jeweils durch Leerzeichen bzw. Tabulatoren voneinander getrennt sind. Diese werden im Folgenden beschrieben.
/etc/inetd.conf | ||
Spalte | Eintrag | Funktion |
1: Service-Name | Name oder Portnummer | Dies ist der Name des Service, wie er in der Datei /etc/services vorkommt. Über diesen Namen und diese Datei ermittelt der Inetd den Port, den er mit diesem Dienst verknüpfen soll. Man kann stattdessen auch einfach die Portnummer verwenden. Namen sind aber meistens übersichtlicher. |
2: Socket-Typ | stream oder dgram | Meistens stream (kontinuierlicher Datenstrom), manchmal aber auch dgram (einzelne Datenpakete). |
3: Protokoll | tcp oder udp | Bei tcp muss die vorhergehende Option stream gewählt werden, bei udp dgram . Wenn man unsicher ist und in der Dokumentation des jeweiligen Dienstes keine Angabe hierzu findet, ist meistens tcp richtig. |
4: wait/nowait | wait oder nowait | wait bedeutet, dass auch alle weiteren Pakete an diesen Port an denselben Prozess weitergeleitet werden. nowait bedeutet, dass der Prozess abgetrennt und der Port für neue Verbindungen wieder frei gemacht wird. TCP-(Stream-)Dienste sollten immer die Option nowait haben. Bei Dgram-Diensten hängt das von der Funktionsweise ab. |
5: Benutzerkonto | z.B. root oder nobody | Unter dieser Benutzerkennung wird der Dienst gestartet. Damit kann man den Service mit niedrigeren Rechten als unter Root starten, was der Sicherheit zugute kommt. Optional kann man abgetrennt durch einen Punkt auch eine Gruppe angeben. |
6: Server-Programm | Pfad/zum/Programm | Hier muss der volle Pfad des Programmes stehen, das den Serverdienst bereitstellt. Im Falle eines internen Dienstes des Inetd (s.u.) muss hier die Zeichenkette internal stehen. |
7: Kommandozeilen-Argumente | Programmname , ggf. Optionen | Hier gehören die Argumente hin, die man dem Server-Programm übergeben möchte. Diese Spalte erstreckt sich in jedem Fall bis zum Ende der Zeile, und es sind auch Leerzeichen erlaubt.Achtung!Das erste Argument muss der Programmname sein. Erst dann kommen die eigentlichen Argumente. internal stehen. |
Einige triviale Dienste, die traditionell zu Testzwecken auf Unix-Servern liefen, sind direkt in den Inetd eingebaut und können in der Konfigurationsdatei über das Schlüsselwort internal
referenziert werden. Da diese Dienste wenig praktischen Nutzen haben und in der Vergangenheit öfter für Denial-of-Service-Angriffe missbraucht wurden, trifft man sie heutzutage nur noch sehr selten in aktiviertem Zustand an. Alle diese Dienste sind stream/tcp
-Dienste.
Man kann auf diese Dienste mit einem Telnet-Client zugreifen. Um sie zu beenden, muss man
Strg +
] drücken und den Befehl quit
absenden.
$ telnet lucid-lamp echo
Ausgabe:
Trying 192.168.4.55... Connected to lucid-lamp.otze. Escape character is '^]'. test test
Beenden:
^] telnet> quit
Connection closed.
Interne Dienst für inetd | ||
Dienst | Port | Funktion |
echo | Port 7 | Dieser Dienst schickt immer genau die Zeichenketten zurück, die man an ihn sendet. |
discard | Port 9 | Dieser Dienst verschluckt alle Eingaben und sendet nie etwas zurück. |
daytime | Port 13 | Dieser Dienst antwortet mit der genauen Zeit, die auf dem Server gilt, und beendet daraufhin die Verbindung. |
chargen | Port 19 | Dieser Dienst antwortet mit einem endlosen Strom von ASCII-Zeichen, der erst endet, wenn man selber die Verbindung abbricht. |
time | Port 37 | Dieser Dienst liefert ebenfalls die Serverzeit, allerdings in einem maschinenlesbaren Format. |
# Legende: # Service Typ Proto Wait User Programm Argumente # Interne Dienste. Auskommentiert, weil sinnlos: #echo stream tcp nowait nobody internal internal #discard stream tcp nowait nobody internal internal #chargen stream tcp nowait nobody internal internal #daytime stream tcp nowait nobody internal internal #time stream tcp nowait nobody internal internal # swat - Samba Web Administration Tool: swat stream tcp nowait root /usr/sbin/swat swat # Ein trivialer eigener "Dienst", der auf Port 3000 antwortet: 3000 stream tcp nowait nobody /bin/echo echo Hallo Welt!
TCP-Wrapper ist eine Bibliothek, mit der man Zugriffskontrollen für TCP-Verbindungen implementieren kann. Mit Hilfe des Inetds und des tcpd
kann man diese Kontrollen praktischerweise für jeden inetd-fähigen Service implementieren. Nebenbei wird auch noch jeder Zugriffsversuch im syslog und daemon.log festgehalten.
Um einen inetd-Service über TCP-Wrapper zu schützen, muss man nur den Pfad des tcpd-Programms eintragen. Das eigentliche Server-Programm wird mit vollem Pfad als erstes Argument eingetragen, z.B. so:
# tcp-wrapper-geschützte Dienste swat stream tcp nowait root /usr/sbin/tcpd /usr/sbin/swat 3000 stream tcp nowait nobody /usr/sbin/tcpd /bin/echo Hallo Welt!
Auch einige Stand-alone-Dienste wie z.B. openssh
und portmap
nutzen die TCP-Wrapper-Bibliothek, die sich im Paket libwrap0 befindet. In diesen Fällen gilt der folgende Abschnitt also auch.
Der openbsd-inetd
-Server hat ebenfalls eingebaute libwrap-Unterstützung. Diese lässt sich durch Anlegen der Datei /etc/default/openbsd-inetd mit der einzigen folgenden Zeile aktivieren: (Neustart des Inetd-Servers erforderlich.)
OPTIONS="-l"
In diesem Fall braucht man nicht extra /usr/sbin/tcpd aufrufen, sondern die im Folgenden beschriebenen hosts_access-Dateien werden in jedem Fall beachtet.
Geregelt wird der Zugriff auf tcp-wrapper-geschützte Dienste durch die Dateien /etc/hosts.allow und /etc/hosts.deny (auch als hosts_access-Dateien bezeichnet). Diese können beliebig viele Regeln beinhalten, je eine pro Zeile. TCP-Wrapper geht bei jeder eingehenden Verbindung erst die hosts.allow- und dann die hosts.deny-Datei durch und stoppt, wenn eine Regel passt. Hierbei wiegt eine Erlaubnis per hosts.allow höher als ein Verbot per hosts.deny, und weiter oben stehende Regeln haben höhere Priorität. Passt keine einzige Regel, so wird die Verbindung ebenfalls zugelassen.
Am sichersten ist man, wenn man ALL: ALL
in der hosts.deny einträgt und dann die Ausnahmen in der hosts.allow aufführt.
Wie erwähnt, benutzt auch der OpenSSH-Server diese Dateien. Man sollte also bei entfernten Rechnern Vorkehrungen treffen, damit man sich nicht selber aussperrt. Da diese Sperre nur neue Verbindungen betrifft, kann man nach einer Änderung der hosts_access-Dateien in einem weiteren Terminal testen, ob ein Login noch möglich ist, während man die ursprüngliche Shell offen hält. Am besten trägt man erstmal folgende Zeile in die hosts.allow-Datei ein:
sshd: ALL
Beide Dateien benutzen dieselbe Syntax, nur dass eben die Logik entgegengesetzt funktioniert. Leerzeilen und Kommentarzeilen (mit # am Anfang) werden ignoriert.
Am Ende der jeweiligen Dateien muss unbedingt ein Zeilenvorschub stehen. Steht am Ende der Datei eine Regel ohne abschließenden Zeilentrenner, so wird diese nicht korrekt verarbeitet.
Jede Zeile besteht aus dem Namen des Services, einem Doppelpunkt und einer Liste der berechtigten oder unberechtigten Clients.
Hier muss der Name des Programms eingetragen werden, nicht der Name des Ports, auf dem der Dienst lauscht! Das spezielle Wort ALL
bezeichnet alle Dienste.
Hier gibt es verschiedene Formen, die betreffenden Clients festzulegen. Die wichtigsten zeigt die folgende Tabelle:
Clients | |
Client | Funktion |
ALL | Passt auf alle Hosts |
LOCAL | Passt auf alle Hosts, deren Name keinen Punkt enthält |
host.domain.tld | Hostname |
w.x.y.z | IP-Adresse |
.domain.tld | Domain |
x.y.z. | Adress-Bereich, dessen IPs mit x.y.z. anfangen |
w.x.y.z/n | Netzmaske |
/etc/hosts.deny:
# Alles verbieten, was nicht explizit erlaubt wird ALL: ALL
/etc/hosts.allow:
# Alle Verbindungen vom selben Rechner erlauben: ALL: localhost # Allen Rechnern der lokalen Domain Zugriff auf den Finger-Daemon erlauben in.fingerd: LOCAL # Unseren Hallo-Welt-Service für zwei bestimmte Rechner und ein Subnetz freigeben: echo: 192.168.0.0/24 10.2.3.4 testserver.woauchimmer.de
Die hosts_access-Sprache ist noch viel mächtiger und besitzt noch viel mehr Optionen als hier dargestellt. Weitere Informationen findet man in den Manpages hosts_access (5) und hosts_options (5).
Diese Revision wurde am 23. März 2012 12:59 von aasche erstellt.