[[Vorlage(Getestet, general)]] {{{#!vorlage Wissen [:Pakete_installieren: Installation von Programmen] [:Terminal: Ein Terminal öffnen] [:Editor: Einen Editor öffnen] [:Dienste: Serverdienste starten/stoppen] }}} [[Inhaltsverzeichnis(2)]] 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 [wikipedia:Socket: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). [[Anker(install)]] = Installation = 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'') Inkompatible Varianten: * '''xinetd''' (siehe unten) kann Einzeldateien pro Dienst, nützlich für [github:puppetlabs/puppetlabs-inetd:Puppet] u.ä. Folgendes Paket ist optional, aber empfohlen: {{{#!vorlage Paketinstallation tcpd, Zugriffsbeschränkungen über TCP-Wrappers [#tcpwrapper s.u.] }}} 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. [[Anker(konfig)]] = Konfiguration = 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]: {{{#!vorlage Befehl 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. ||<-3 rowclass="titel"> /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, wenn inetd ihnen __Verbindungen__ übergeben soll, d.h. jeweils einen Client Socket, mit dem der Dienst per Standardein- und ausgabekanal kommunizieren kann.\\ TCP mit "wait" führt dazu, dass der Dienst stattdessen den Serverkanal ([http://manpages.ubuntu.com/manpages/trusty/man8/inetd.8.html "master socket"]) übergeben bekommt. Analogie: Wenn ein Anruf reinkommt, startet inetd den Dienst, übergibt ihm das gesamte Telefon, und der Dienst muss dann selbst den Hörer abnehmen.\\ 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 ([#internal 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.{{{#!vorlage Warnung Das erste Argument muss der Programmname sein. Erst dann kommen die eigentlichen Argumente.}}} Für interne Dienste muss hier ebenfalls die Zeichenkette `internal` stehen. || [[Anker(internal)]] == Interne Dienste == 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 [wikipedia:Denial_of_Service: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 [[Vorlage(Tasten, Strg+])]] drücken und den Befehl `quit` absenden. {{{#!vorlage Befehl $ telnet lucid-lamp echo }}} Ausgabe: {{{ Trying 192.168.4.55... Connected to lucid-lamp.otze. Escape character is '^]'. test test }}} Beenden: {{{#!vorlage Befehl ^] telnet> quit }}} {{{ Connection closed. }}} ||<-3 rowclass="titel"> 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. || == Beispielkonfiguration == {{{ # 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! }}} [[Anker(tcpwrapper)]] = TCP-Wrapper = 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! }}} {{{#!vorlage Hinweis 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. }}} {{{#!vorlage Hinweis 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. }}} == hosts_access-Dateien == 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. {{{#!vorlage Warnung 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`` }}} === Syntax === Beide Dateien benutzen dieselbe Syntax, nur dass eben die Logik entgegengesetzt funktioniert. Leerzeilen und Kommentarzeilen (mit '''#''' am Anfang) werden ignoriert. {{{#!vorlage Warnung 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. === Servicename === 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. === Client(s) === Hier gibt es verschiedene Formen, die betreffenden Clients festzulegen. Die wichtigsten zeigt die folgende Tabelle: ||<-2 rowclass="titel"> 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 || === Beispiel === '''/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 }}} {{{#!vorlage Experten 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)''. }}} = Links = * [:xinetd:] - Alternative * [:Serverdienste:] {Übersicht} Übersichtsseite # tag: Netzwerk, Server, System