Original in fr Frédéric Raynal
fr to en Georges Tarbouriech
en to de Harald Radke
xinetd bietet ähnliche Möglichkeiten zur Zugriffssteuerung an, wie der tcp_wrapper. Zusätzlich leistet es noch mehr:
Das Hauptproblem, wie schon erwähnt, stellt die Abwicklung von RPC Aufrufen dar. Jedoch arbeiten portmap und xinetd großartig zusammen.
Im ersten Teil dieses Artikels wird erklärt, wie xinetd funktioniert. Ausführlich wird die Konfiguration des Systems, sowie einige spezielle Optionen (Beschränkung auf ein Netzinterface, Umleitung) beschrieben. Dabei werden zur Veranschaulichung einige Beispiel vorgestellt. Im zweiten Teil schließlich wird xinetd im laufen Betrieb betrachtet und ein Blick auf die Protokolldateien geworfen. Zum Schluß gibt es dann noch einen nützlichen Tip.
Von www.xinetd.org kann man das Programm beziehen.
In diesem Artikel wurde Version 2.1.8.9pre10 verwendet.
Übersetzung und Installation sehen wie üblich aus:
./configure
make
make install,
das wars :)
configure bietet auch hier die üblichen Optionen. Desweiteren gibt es zur Übersetzungszeit drei spezielle Schalter:
Über folgende Signale kann man das Verhalten von xinetd beeinflussen:
Es gibt zwei Werkzeuge namens itox und xconv.pl, welche mit xinetd mitkommen und
den Inhalt von /etc/inetd.conf als Basis für die Konfigurationsdatei von xinetd
verwenden. Damit ist es das natürlich nicht gewesen, da die Regeln, definiert in der
Wrapper Konfiguration, nicht berücksichtigt werden. itox wird wohl nicht mehr weiterentwickelt.
Generell ist xconv.pl die bessere Wahl, auch wenn die Ergebnisse noch zusätzlich
per Hand angepaßt werden müssen, da xinetd mehr Funktionalität als inetd
bietet.
/usr/local/sbin/xconv.pl < /etc/inetd.conf > /etc/xinetd.confAm Anfang der Konfigurationsdatei stehen die Standardeinstellungen. Alle Attribute, die hier zu finden sind, werden für jeden Dienst,der von xinetd verwaltet wird, verwendet. Für jeden Dienst folgt nun ein eigener Bereich, in welchem Standardeinstellungungen angepaßt werden können.
Der Eintrag für die Standardeinstellungen sieht so aus:
defaults
{
attribut operator wert(e)
...
}
Die Werte jedes Attributes, die diesem hier zugwiesen werden, sind für alle folgenden Dienste gültig. Deswegen kann man mittels des Attributes only_from eine feste Liste von IP Adressen angeben, die die Dienste nutzen dürfen:
only_from = 192.168.1.0/24/192.168.5.0/24 192.168.10.17Dadurch dürfen alle Rechner mit obigen Adressen alle hier konfigurierten Dienste in Anspruch nehmen. Aber natürlich können diese Werte zusätzlich noch für jeden Dienst einzeln modifiziert werden (man werfe ein Blick auf die weiter unten vorgestellten Operatoren). Dies ist allerdings ein wenig riskant. Es ist besser, will man das System einfach und sicher halten, nicht erst Standardwerte zu definieren, die dann später für einzelne Dienste wieder angepaßt werden. Betrachtet man beispielsweise Zugriffsrechte, so besteht die einfachste Vorgehensweise darin, zuerst generell den Zugriff zu verbieten und dann für jeden Dienst einzeln die anvisierten Benutzer anzugeben und diesen den Zugriff zu ermöglichen (bei tcp_wrapper wird dies dadurch realisiert, dass zuerst in der Datei hosts.deny die Regel ALL:ALL@ALL eingetragen wird und dann in hosts.allow alle zugelassenen Dienste und die erlaubten IP Adressen etwaiger Benutzer angegeben werden).
Die Syntax eines Eintrags für einen Dienst in xinetd.conf sie folgendermaßen aus:
service { attribut operator wert(e) ... }Als Operatoren stehen zur Auswahl: =, += und -=. Die meisten Attribute lassen jedoch nur den Operator = zu. Dieser weist einem Attribut einen bestimmten Wert zu. Durch += wird ein Eintrag einer Liste von Werten hinzugefügt, mittels -= hingegen wird der Eintrag aus der Liste entfernt.
Tabelle 1 gibt eine kurze Übersicht der Attribute. Deren Einsatz wird in einigen Beispielen verdeutlicht werden. Weitergehende Informationen kann man der Manpage zu xinetd.conf entnehmen.
Attribut | Werte und Beschreibung |
Flags |
Nur die gängigsten Werte werden hier aufgeführt; weitere sind in der
Dokumentation zu finden:
|
log_type | xinetd verwendet syslogd, als Selektor wird standardmäßig
daemon.info gewählt.
|
log_on_success | Bei Start eines Servers können mehrere unterschiedliche Informationen festgehalten werden:
|
log_on_failure |
Hierdurch kann eine Vielzahl an Informationen protokoliert werden, sobald
ein Server nicht gestartet werden kann, sei es aufgrund fehlender Resourcen oder
der Verletzung der Zugriffsregeln:
|
nice | Ändert die Priorität des Servers, analog dem Unixbefehl nice. |
no_access | Liste der Clients, denen der Zugriff auf den jeweiligen Dienst verweigert werden soll |
only_from | Liste aller akzeptierten Rechner. Wird diesem Attribut kein Wert zugewiesen, so ist kein Zugriff auf den Dienst möglich |
port | Port, unter dem der Dienst erreichbar ist. Sollte dieser auch in der Datei /etc/services stehen, müssen beide Wert übereinstimmen. |
protocol | Das hier angegebene Protokoll muss in der Datei /etc/protocols aufgeführt sein. Wird dieses Attribut nicht gesetzt, wird das Standardprotokoll des Servers verwendete |
server | Pfad, unter dem der Server zu finden ist |
server_args | Parameter, die an den Server übergeben werden sollen |
socket_type | stream (TCP), dgram (UDP), raw (IP Direktzugriff) oder seqpacket () |
type | xinetd verwaltet drei Arten von Diensten:
|
wait |
Legt das threading Verhalten des Dienstes fest. Es gibt zwei Möglichkeiten:
|
cps | Beschränkt die Zahl der zugelassenen Verbindungen. Als erster Parameter wird die Zahl selbst angeben. Der zweite Wert legt die Zeit fest, die der Dienst für weitere Verbindungen erreichbar ist, sobald das Limit erreicht wurde. |
instances | Maximale Zahl an Servern des gleichen Types, die simultan laufen dürfen |
max_load | Tatsächliche maximale Last eines Servers (z.B. 2 oder 2.5). Wird dieser Wert überschritten, nimmt der Server keine weiteren Anfragen an |
per_source | Ein Zahlenwert oder UNLIMITED. Ermöglicht es, die Zahl der Verbindungen, die ein Dienst mit einem einzelnen Clientrechner unterhält, zu beschränken. |
Die letzten vier Attribute in Tabelle 1 bieten die Möglichkeit, die Resourcen je nach Server zu verwalten. Dies stellt einen effizient Schutz vor Denial of Service Angriffen dar (Lahmlegen eines Rechners, indem dessen Resourcen komplett belegt werden).
In diesem Abschnitt wurden ein wenig von der Funktionalität von xinetd vorgestellt. Im nächsten wird nun gezeigt, wie diese angewandt wird und einige Regeln erläutert, so dass xinetd korrekt funktioniert.
Der erste Schritt hin zu einem sicheren System ist, standardmäßig allen Rechnern den Zugriff zu verweigern. Danach wird dann für den jeweiligen Dienst separat festgelegt, wer diesen nutzen darf. Wie gesehen gibt es zwei Attribute, die den Zugriff auf Basis der IP Adresse eines Rechners steuern: only_from und no_access. Unter Verwendung des letzteren:
no_access = 0.0.0.0/0
wird der Zugriff auf alle Dienste unterbunden. Soll dann etwa echo (ping) allen zugängig gemacht werden, sollte in der Sektion für den echo Dienst folgendes stehen:
only_from = 0.0.0.0/0
Unter Verwendung dieser Einstellungen erhält man folgende Ausgabe:
Sep 17 15:11:12 charly xinetd[26686]: Service=echo-stream: only_from list and no_access list match equally the address 192.168.1.1
Bei der Entscheidung, ob ein Zugriff erlaubt werden soll, werden die Adresslisten beider Attribute überprüft. Wird die Adresse des Clientrechners von beiden Listen überdeckt, so ist das Attribut relevant, welches weniger allgemein ist. Kann dies nicht festgestellt werden (beide gleich allgemein), so wird die Verbindung nicht zugelassen. Um dies zu beheben, sollte man stattdessen folgendes schreiben:
only_from = 192.0.0.0/8Eine einfachere Lösung besteht darin, in der Sektion defaults folgendes Attribut zu verwenden:
only_from =Wird kein Wert zugewiesen, scheitert jeder Verbindungsaufbau :)
Wichtig, ganz wichtig: wird gar keine Zugriffsregel (also weder das Attribut only_from, noch no_access) für einen Dienst aufgestellt (weder in dessen, noch in der defaults Sektion), so kann jeder diesen Dienst nutzen!
Ein Beispiel für die defaults Sektion:
defaultsMittels servers, services und xadmin unter #INTERNAL kann xinetd gesteuert werden. Später dazu mehr.
{
instances = 15
log_type = FILE /var/log/servicelog
log_on_success = HOST PID USERID DURATION EXIT
log_on_failure = HOST USERID RECORD
only_from =
per_source = 5disabled = shell login exec comsat
disabled = telnet ftp
disabled = name uucp tftp
disabled = finger systat netstat#INTERNAL
disabled = time daytime chargen servers services xadmin#RPC
disabled = rstatd rquotad rusersd sprayd walld
}
Einige Attribute müssen, je nach Art des Dienstes (INTERNAL, UNLISTED oder RPC), angegeben werden:
Attribut | Verwendung |
socket-type | Jeder Dienst |
user | Nur Dienste, die keine INTERNAL Dienste sind |
server | Nur Dienste, die keine INTERNAL Dienste sind |
wait | Alle Dienste |
protocol | Alle RPC Dienste und solche, die nicht in /etc/services zu finden sind |
rpc_version | Jeder RPC Dienst. |
rpc_number | Jeder RPC Dienst ohne Eintrag in /etc/rpc. |
port | Jeder Dienst, der kein RPC Dienst ist und nicht in/etc/services steht |
Hier ein Beispiel, wie die Konfiguration von Diensten aussieht:
service ntalkMan beachte, dass diese Dienste nur im lokalen Netzwerk zugäglich sind (293.268.1.0/24). Was FTP angeht, so wurde der Zugriff noch weiter eingeschränkt: Nur 4 Rechnern wurde der Zugriff gestattet und dies auch nur zu bestimmten Zeiten.
{
socket_type = dgram
wait = yes
user = nobody
server = /usr/sbin/in.ntalkd
only_from = 192.168.1.0/24
}service ftp
{
socket_type = stream
wait = no
user = root
server = /usr/sbin/in.ftpd
server_args = -l
instances = 4
access_times = 7:00-12:30 13:30-21:00
nice = 10
only_from = 192.168.1.0/24
}
Angenommen, eine Firma möchte einen FTP Server füpr ihre Angestellten installieren, etwa, damit diese auf interne Dokumente zugreifen und diese lesen können. Desweiteren sollen Kunden mittels FTP auf die Firmenprodukte zugreifen können. bind ist wie geschaffen für diesen Fall :) Es werden zwei FTP Dienste definiert. Diese müssen allerdings von xinetd unterschieden werden können. Dazu wird das Attribut id verwendet. Durch dieses wird ein Dienst eindeutig identifiziert. Sollte ein Dienst dem Attribut keinen Wert zuweisen, so wird standardmäßig der Dienstname als Wert verwendet.
service ftpDurch den Einsatz von bind kann das jeweilige Daemonprogramm angesprochen werden, abhängig von der Zieladresse der Pakete. Will ein Client im lokalen Netzwerk auf intere Daten zugreifen, so muss er die lokale Adresse (bzw. den assoziierten Rechnernamen) des FTP Servers verwenden. In der Protokolldatei steht dann:
{
id = ftp-public
wait = no
user = root
server = /usr/sbin/in.ftpd
server_args = -l
instances = 4
nice = 10
only_from = 0.0.0.0/0 #allows every client
bind = 212.198.253.142 #public IP address for this server
}service ftp
{
id = ftp-private
socket_type = stream
wait = no
user = root
server = /usr/sbin/in.ftpd
server_args = -l
only_from = 192.168.1.0/24 #only for internal use
bind = 192.168.1.1 #local IP address for this server (charly)
}
00/9/17@16:47:46: START: ftp-public pid=26861 from=212.198.253.142Der erste Teil stammt vom Befehl ftp 212.198.253.142, während der zweite Teil vom Aufruf von charly auf sich selbst resultiert: ftp 192.168.1.1.
00/9/17@16:47:46: EXIT: ftp-public status=0 pid=26861 duration=30(sec)
00/9/17@16:48:19: START: ftp-internal pid=26864 from=192.168.1.1
00/9/17@16:48:19: EXIT: ftp-internal status=0 pid=26864 duration=15(sec)
Was passiert aber nun, falls ein Rechner keine zwei statischen IP Adressen hat ? Dies ist zum Beispiel bei PPP Verbindungen oder beim Einsatz von DHCP der Fall. Es wäre besser, könnten Dienste an Netzwerkschnittstellen selbst, anstatt an Adressen gebunden werden. Dies jedoch ist bei xinetd noch nicht in Sicht und stellt ein wirkliches Problem dar. Das Design eines C Modules beispielsweise, dass auf ein Netzwerkinterface oder eine Adresse zugreifen soll, ist stark vom jeweiligen Betriebssystem abhängig, und da xinetd auf vielen Plattformen arbeiten soll...Unter Verwendung eines Skriptes kann das Problem gelöst werden:
#!/bin/shDieses Skript liest die gewünschte Konfiguration aus der Datei /etc/xinetd.base aus, wobei PUBLIC_ADDRESS als Platzhalter für die dynamische Adresse steht und nimmt die entsprechenden Änderungen in /etc/xinetd.conf vor. Hierbei wird PUBLIC_ADDRESS durch die Adresse ersetzt, die dem Interface zugeordnet ist, welches dem Skript als Parameter übergeben wird. Der Aufruf des Skriptes hängt von der Art der Verbindung ab: am einfachsten ist es, den Aufruf in die jeweilige ifup-* Datei einzutragen und xinetd neu zu starten.PUBLIC_ADDRESS=`/sbin/ifconfig $1 | grep "inet addr" | awk '{print $2}'| awk -F: '{print $2}'`
sed s/PUBLIC_ADDRESS/"$PUBLIC_ADDRESS"/g /etc/xinetd.base > /etc/xinetd.conf
telnet serviceDabei passiert folgendes:
{
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/sbin/in.telnetd
only_from = 192.168.1.0/24
redirect = 192.168.1.15 23
}
>>telnet charlyEs scheint, als ob eine Verbindung mit dem Rechner charly aufgebaut worden ist. Tatsächlich aber befindet sich sabrina auf der anderen Seite der Verbindung (eine Alpha Maschine, auch an "Digital UNIX" zu erkennen). Die Weiterleitung kann recht nützlich, aber auch gefährlich sein. Wird sie eingerichtet, so muss auf beiden Rechnern protokolliert werden. Desweiteren wird für diese Art von Dienst der Einsatz von DMZ und Firewall empfohlen ;-)
Trying 192.168.1.1...
Connected to charly.
Escape character is '^]'.
Digital UNIX (sabrina) (ttyp1)
login:
defaults {Bevor sie dann aktiviert werden sollten einige Vorkehrungen getroffen werden:
...
disabled = servers services xadmin
...
}
service xadminDer Dienst xadmin bietet fünf Befehle:
{
type = INTERNAL UNLISTED
port = 9100
protocol = tcp
socket_type = stream
wait = no
instances = 1
only_from = 192.168.1.1 #charly
}
Es wird nur der Dienst finger benötigt
finger servicexinetd wurde ohne die Option --with-libwrap übersetzt (siehe das Attribut server). Der Abschnitt defaults sieht wie weiter oben aus, jeder Zugriff auf charly wird unterbunden, egal, woher die Anfrage kommen mag. Der finger Dienst ist nicht deaktiviert, und dennoch:
{
flags = REUSE NAMEINARGS
server = /usr/sbin/tcpd
server_args = in.fingerd
socket_type = stream
wait = no
user = nobody
only_from = 192.168.1.1 #charly
}
pappy@charly >> finger pappy@charly
[charly]
pappy@charly >>pappy@bosley >> finger pappy@charly
[charly]pappy@bosley >>
Die Anfrage scheint weder von charly(192.168.1.1),
einem autorisierten Rechner, noch von bosley
(192.168.1.10) zu funktionieren.
Ein Blick in die Protokolldatei:
/var/log/servicelog :xinetd zufolge wurde die Anfrage von charly aus korrekt bearbeitet (die beiden ersten Zeilen): Zugriff wurde gestattet, der Vorgang dauerte 5 Sekunden. Der Zugriff von bosley aber wurde abgelehnt (FAIL).
00/9/18@17:15:42: START: finger pid=28857 from=192.168.1.1
00/9/18@17:15:47: EXIT: finger status=0 pid=28857 duration=5(sec)
00/9/18@17:15:55: FAIL: finger address from=192.168.1.10
/var/log/services :Es existiert dort nur Eintrag, der auf die beiden Anfragen passt! Die Anfrage von bosley (die zweite) wurde von xinetd abgefangen, weswegen sie auch in dessen Protokolldatei auftaucht. Obige Zeile also ist wirklich das Resultat der Anfrage von charly an charly, Zeit und PID sind gleich. Diese wurde von xinetd eigentlich zugelassen.
Sep 18 17:15:42 charly in.fingerd[28857]: refused connect from 192.168.1.1
Zusammengefasst:
Durch die Art und Weise, wie die Einträge server und server_args der Dienste definiert worden sind, ist die Wrapperfunktionalität verwendbar (banner - es gibt ein Attribut namens banner, spawn, twist,...). Es darf nicht vergessen werden, dass durch die Option --with-libwrap zur Übersetzungszeit nur die Steuerung der Zugriffsrechte (unter Zuhilfenahme von hosts.allow und hosts.deny) durch xinetd selbst ermöglicht wird, bevor dann der jeweilige Prozess gestartet wird. Dieses Beispiel zeigt, dass es mit obiger Konfiguration weiterhin möglich ist, die Funktionalität des TCP Wrappers zu nutzen.
Die Überschneidung von Funktionalitäten kann, falls sie überhaupt funktioniert, zu recht merkwürdigen Ergebnissen führen. Statt xinetd zusammen mit inetd und portmap einzusetzen, sollten Dienste besser von nur einem dieser "Super Daemonen" verwaltet werden.
chroot [options] new_rootAuf diese Weise werden häufig Dienste wie bind/DNS oder FTP gesichert. Um dies zuerreichen und dabei gleichzeitig die Vorzüge von xinetd nutzen zu können, muss chroot als Server deklariert werden. Die Parameter werden dann über das Attribut server_args übergeben :)
service ftpSobald nun eine Anfrage, den jeweiligen Dienst betreffend, eintrifft, wird als erstes chroot ausgeführt. Das erste Argument, dass diesem übergeben wird, ist der erste Eintrag in sever_args: das neue Wurzelverzeichnis. Zuletzt wird der Server gestartet.
{
id = ftp
socket_type = stream
wait = no
user = root
server = /usr/sbin/chroot
server_args = /var/servers/ftp /usr/sbin/in.ftpd -l
}
Es mag sich nun die Frage stellen, ob nun xinetd oder inetd verwendet werden sollte. Es ist nun einmal so, dass xinetd ein wenig mehr Administration verlangt, vorallem, solange es nicht mit den Linux Distributionen mitkommt (Aussnahme: RedHat 7.0). Eine sichere Lösung stellt der Einsatz von xinetd auf Rechnern dar, die eine Verbindung mit dem Rest der Welt (etwa dem Internet) haben. xinetd bietet einfach den besseren Schutz. Für Rechner in einem lokalen Netzwerk sollte inetd vollkommen ausreichend sein.