|
|
|
|
Linux Netzwerker-HandbuchTony Bautts, Terry Dawson & Gregor N. Purdy 3. Auflage Juli 2005 ISBN 3-89721-414-8 382 Seiten Weitere Informationen zur gedruckten Version des Buches finden Sie unter: www.oreilly.de/catalog/linag3ger/ Zur Übersicht aller OpenBooks |
Nachdem Sie IP und den Resolver (DNS) erfolgreich eingerichtet haben, müssen Sie sich den Diensten zuwenden, die Sie in Ihrem Netzwerk anbieten wollen. Dieses Kapitel behandelt die Konfiguration einiger einfacher Netzwerkanwendungen, einschließlich der inetd- und xinetd-Server und der Programme aus der rlogin-Familie. Wir behandeln außerdem kurz die RPC-Schnittstelle (Remote Procedure Call), auf der Dienste wie das Network File System (NFS) basieren. Die Konfiguration von NFS dagegen ist komplizierter und wird in diesem Buch nicht beschrieben.
Natürlich können wir nicht alle Netzwerkanwendungen in diesem Buch beschreiben. Falls Sie einen Dienst installieren wollen, auf den wir hier nicht eingehen, schauen Sie in die entsprechenden Manpages.
Programme, die Anwendungsdienste über das Netzwerk bereitstellen, werden als Netzwerk-Dämonen bezeichnet. Ein Dämon ist ein Programm, das einen bestimmten Port öffnet und auf eingehende Verbindungen wartet. Wird eine solche Verbindung aufgebaut, erzeugt der Dämon einen Kind-Prozess, der die Verbindung übernimmt, während er selbst weiter nach eingehenden Anforderungen Ausschau hält. Dieses an sich gute Konzept hat den Nachteil, dass für jeden angebotenen Dienst ein entsprechender Dämon im Hauptspeicher laufen muss. Außerdem müssen in jedem einzelnen Netzwerk-Dämon, der für die Verbindungsüberwachung und die Verwaltung der Ports zuständig ist, immer wieder dieselben Softwareroutinen eingebunden werden.
Um diesen Mangel an Effizienz zu überwinden, verwenden nahezu alle Unix-Installationen einen speziellen Netzwerk-Dämon, den man als »Super-Server« auffassen kann und der Sockets für eine Reihe von Diensten erzeugt und simultan abhört. Fordert ein entfernter Host einen Dienst über einen dieser Sockets an, wird das vom Super-Server registriert, und er startet den für diesen Port zuständigen Server. Der Socket wird dann an den Kind-Prozess übergeben, und der Super-Server fährt daraufhin mit dem Abhören der Sockets fort.
Der am häufigsten verwendete Super-Server ist inetd, der »Internet-Dämon«. Er wird während der Boot-Phase des Systems gestartet und liest eine Liste der Dienste, die er verwalten soll, aus der Datei /etc/inetd.conf. Außer diesen Servern gibt es eine Reihe trivialer Dienste, so genannte interne Dienste, die inetd selbstständig ausführt. Dazu gehören beispielsweise chargen, das einfach eine Zeichenkette erzeugt, und daytime, das die nach Meinung des Systems aktuelle Tageszeit zurückliefert.
Ein Eintrag in dieser Datei besteht aus einer einzelnen Zeile, die sich aus den folgenden Feldern zusammensetzt:
Die Bedeutung der Felder wird nachfolgend erklärt:
Ein Beispiel für inetd.conf finden Sie in Beispiel 10-1. Der finger-Dienst ist auskommentiert und steht daher nicht zur Verfügung. Das geschieht häufig aus Sicherheitsgründen, weil er von Angreifern dazu verwendet werden kann, um Namen und andere Details der Benutzer Ihres Systems zu ermitteln.
Der tftp-Dämon ist ebenfalls auskommentiert. tftp implementiert das Trivial File Transfer Protocol (TFTP), das es einem erlaubt, allgemein lesbare Dateien ohne Kennwortprüfung von Ihrem System zu übertragen. Das ist vor allem bei der Datei /etc/passwd gefährlich, umso mehr, wenn Sie keine Shadow-Passwörter benutzen.
tftp wird üblicherweise von plattenlosen Clients und X-Terminals benutzt, um deren Code von einem Boot-Server herunterzuladen. Falls Sie den tftpd-Dämon aus diesem Grund ausführen müssen, stellen Sie sicher, dass Sie den Zugriff auf diejenigen Verzeichnisse beschränken, aus denen die Clients die Dateien beziehen. Diese Verzeichnisse können Sie auf der tftpd-Kommandozeile angeben. Wie das geht, ist auf der zweiten tftp-Zeile im Beispiel zu sehen.
Da die Erweiterung eines Computers um Netzwerkfähigkeiten viele Sicherheitsrisiken in sich birgt, sind die Anwendungen so entwickelt worden, dass sie sich vor verschiedenen Arten von Angriffen schützen können. Allerdings sind einige Sicherheitsmerkmale fehlerhaft (was der RTM-Internet-Wurm auf besonders drastische Weise in einer Reihe von Programmen demonstrierte, zu denen auch alte Versionen des sendmail-Dämons gehörten) oder es wird nicht unterschieden zwischen sicheren Hosts, von denen Anforderungen nach einem bestimmten Dienst akzeptiert werden können, und unsicheren Hosts, deren Anforderungen abgelehnt werden müssen. Die Dienste finger und tftp hatten wir ja bereits angesprochen. Netzwerkadministratoren würden den Zugriff auf diese Dienste gerne auf »vertrauenswürdige Hosts« beschränken, was aber mit dem normalen Setup, bei dem inetd den Dienst entweder allen Clients anbietet oder überhaupt keinem, nicht möglich ist.
Ein für die Verwaltung hostspezifischer Zugriffe nützliches Werkzeug ist tcpd, das oft auch als Dämon-»Wrapper« bezeichnet wird. Es wird für TCP-Dienste, die Sie überwachen oder schützen wollen, anstelle des normalen Serverprogramms gestartet. tcpd prüft, ob der entfernte Host einen solchen Dienst überhaupt benutzen darf, und führt nur dann das eigentliche Serverprogramm aus. tcpd schickt auch eine Meldung über die Anforderungen an den syslog-Dämon. Beachten Sie, dass dies bei UDP-basierten Diensten nicht funktioniert.
Um beispielsweise den finger-Dämon mit einem Wrapper zu schützen, müssen Sie die entsprechende Zeile in inetd.conf
Ohne eine zusätzliche Zugriffskontrolle erscheint dies für den Client wie ein ganz gewöhnliches finger-Setup, mit der Ausnahme, dass alle Anforderungen im auth-Kanal von syslog aufgezeichnet werden.
Die Zugriffskontrolle wird mit Hilfe der beiden Dateien /etc/hosts.allow und /etc/hosts.deny implementiert. Sie enthalten Einträge, die den Zugriff auf bestimmte Dienste und Hosts erlauben oder verweigern. Wenn tcpd eine Anforderung für einen Dienst wie finger von einem Client-Host namens biff.foobar.com behandelt, durchsucht es hosts.allow und hosts.deny (in dieser Reihenfolge) nach einem Eintrag, bei dem sowohl der Dienst als auch der Client übereinstimmen. Wird ein passender Eintrag in hosts.allow gefunden, wird der Zugriff freigegeben, unabhängig davon, ob es noch einen Eintrag in hosts.deny gibt. Wird keine Übereinstimmung in hosts.allow, aber eine in hosts.deny gefunden, wird die Anforderung abgewiesen, indem die Verbindung unterbrochen wird. Die Anforderung wird akzeptiert, wenn überhaupt kein passender Eintrag gefunden wird.
Die Einträge in den Zugriffsdateien sehen folgendermaßen aus:
dienstliste ist eine Liste mit Dienstbezeichnungen aus /etc/services oder das Schlüsselwort ALL. Damit der Eintrag alle Dienste bis auf finger und tftp betrifft, geben Sie ALL EXCEPT finger, tftp an.
hostliste ist eine Liste mit Hostnamen, IP-Adressen oder den Schlüsselwörtern ALL, LOCAL, UNKNOWN oder PARANOID. ALL steht für alle Hosts, während LOCAL nur Hostnamen erfasst, die keinen Punkt enthalten.1 UNKNOWN gilt für jeden Host, dessen Name oder Adresse nicht durch Nachschlagen ermittelt werden konnte. PARANOID gilt für jeden Host, dessen Name sich nicht zu seiner IP-Adresse auflösen lässt.2 Ein Name, der mit einem Punkt beginnt, gilt für alle Hosts, deren Domain mit diesem Namen übereinstimmt. Zum Beispiel passt .foobar.com zu biff.foobar.com, nicht aber zu nurks.fredsville.com. Ein Muster, das mit einem Punkt endet, gilt für jeden Host, dessen IP-Adresse mit dem angegebenen Muster beginnt. So passt 172.16. zu 172.16.32.0, nicht aber zu 172.15.9.1. Ein Muster der Form n.n.n.n/m.m.m.m wird als IP-Adresse und Netzmaske betrachtet. Wir könnten daher unser Beispiel von eben auch als 172.16.0.0/255.255.0.0 angeben. Schließlich können Sie mit einem Muster, das mit einem »/«-Zeichen beginnt, eine Datei festlegen, von der angenommen wird, dass sie eine Liste mit Hostnamen- oder IP-Adressmustern enthält, von denen jedes zutreffen darf. So würde die Angabe /var/access/trustedhosts den tcpd-Dämon veranlassen, diese Datei zu lesen und zu prüfen, ob irgendeine der darin enthaltenen Zeilen zum verbindenden Host passt.
Um nur den lokalen Hosts den Zugriff auf finger und tftp zu gestatten, lassen Sie die Datei /etc/hosts.allow leer und tragen in /etc/hosts.deny Folgendes ein:
Das optionale Feld shellbefehl kann einen Shell-Befehl enthalten, der ausgeführt wird, wenn der Eintrag passt. Das ist sinnvoll, wenn Sie Fallen einrichten wollen, die potenzielle Angreifer enttarnen. Das folgende Beispiel erzeugt eine Protokolldatei, die den verbindenden Benutzer und den Host anzeigt. Wenn dieser Host nicht vlager.vbrew.com ist, werden die Ausgaben einer finger-Anwendung auf diesen Host dort eingetragen:
Die Argumente %h und %d werden von tcpd zum Client-Hostnamen bzw. zum Dienstnamen erweitert. Details entnehmen Sie bitte der Manpage hosts_access(5).
Mit xinetd ist eine Alternative zum normalen inetd aufgetaucht, die inzwischen weithin akzeptiert wird. Sie wird als sicherer und robuster eingestuft und bietet Schutz vor einigen DoS-Angriffen, die gegen inetd ausgeführt wurden. Die zahlreichen Funktionen und Eigenschaften, die von xinetd angeboten werden, lassen es außerdem als eine sehr verlockende Alternative erscheinen. Hier ist eine kurze Liste seiner Funktionen:
xinetd ist mittlerweile standardmäßig Bestandteil der meisten Linux-Distributionen. Falls Sie den neuesten Quellcode oder aktuelle Informationen darüber suchen, schauen Sie auf die Website http://www.xinetd.org. Wenn Sie das Programm kompilieren und IPv6 benutzen, dürfen Sie nicht vergessen, die Option --with-inet6 einzustellen.
Die Konfiguration von xinetd ist etwas anders, aber dennoch nicht komplizierter als die von inetd. Anstatt eine Master-Konfigurationsdatei für alle Dienste zu erzwingen, kann xinetd so konfiguriert werden, dass es eine Master-Konfigurationsdatei namens /etc/xinetd.conf und separate Konfigurationsdateien für jeden zusätzlichen konfigurierten Dienst verwendet. Neben einer vereinfachten Konfiguration gestattet dies eine feinere Einstellung jedes Dienstes und führt zu einer größeren Flexibilität von xinetd.
Die erste Datei, die Sie konfigurieren müssen, ist /etc/xinetd.conf. Eine Beispieldatei sieht so aus:
Es gibt eine Reihe von Optionen, die konfiguriert werden können. Die oben verwendeten Optionen sind:
All diese Optionen können in den Konfigurationsdateien der einzelnen Dienste überschrieben werden, die wir im Verzeichnis /etc/xinetd.d ablegen. Diese Optionen in der Master-Konfigurationsdatei dienen als Vorgabewerte. Die Konfiguration einzelner Dienste ist eben-so einfach. Hier ist ein Beispiel des FTP-Dienstes, der für xinetd konfiguriert wurde:
Als Erstes werden Sie feststellen, dass die einzelnen Dienste im Verzeichnis xinetd.d dankenswerterweise sinnvoll benannt sind, was es einfacher macht, die entsprechenden Konfigurationsdateien zu identifizieren und zu verwalten. In diesem Fall heißt die Datei einfach vsftp, was sich auf den Namen des von uns verwendeten FTP-Servers bezieht.
Schauen Sie sich das Beispiel an. Die erste aktive Konfigurationszeile definiert den Namen des Dienstes, der konfiguriert wird. Was für eine Überraschung, der Diensttyp wird durch die Anweisung service definiert! Der Rest der Konfiguration ist in geschweiften Klammern enthalten, fast wie C-Funktionen. Einige der Optionen, die in den Dienstkonfigurationen zu finden sind, überschneiden sich mit denjenigen aus dem defaults-Abschnitt. Wenn ein Element in den defaults definiert ist und dann noch einmal in der Konfiguration eines Dienstes definiert wird, hat dieser letzte Wert Vorrang. Es stehen viele Konfigurationsoptionen zur Verfügung, die auch ausführlich in der xinetd.conf-Manpage diskutiert werden. Um einen Dienst jedoch grundsätzlich zum Laufen zu bringen, brauchen wir nur ein paar Optionen:
Die Portnummern, über die bestimmte »Standard«-Dienste angeboten werden, sind im Assigned Numbers-RFC definiert. Um Server- und Client-Programme dazu zu bringen, Dienstnamen in diese Nummern umzuwandeln, ist zumindest ein Teil dieser Liste auf jedem Host vorhanden, und zwar in einer Datei namens /etc/services. Ein Eintrag setzt sich aus folgenden Bestandteilen zusammen:
Hier gibt dienst den Namen des Dienstes an, port definiert, auf welchem Port dieser Dienst angeboten wird, und protokoll definiert das zu verwendende Transportprotokoll. Im Allgemeinen ist dies entweder udp oder tcp. Ein Dienst kann für mehr als ein Protokoll angeboten werden. Genauso können verschiedene Dienste am gleichen Port angeboten werden, solange die Protokolle verschieden sind. Im Feld aliase können Sie alternative Namen für denselben Dienst angeben.
Normalerweise müssen Sie die services-Datei, die der Netzwerksoftware auf Ihrem Linux-System beiliegt, nicht ändern. Dennoch wollen wir Ihnen in Beispiel 10-2 einen kleinen Ausschnitt aus dieser Datei zeigen.
Wie die services-Datei benötigt die Netzwerkbibliothek eine Möglichkeit, um Protokollnamen - beispielsweise die in der services-Datei verwendeten - in Protokollnummern zu übersetzen, die von der IP-Schicht auf anderen Hosts verstanden werden. Dazu wird der Name in der Datei /etc/protocols nachgeschlagen. Diese Datei enthält einen Eintrag pro Zeile, in dem jeweils ein Protokollname und die ihm zugewiesene Nummer steht. Dass Sie sich mit dieser Datei auseinander setzen müssen, ist allerdings noch unwahrscheinlicher als bei /etc/services. Wie die Datei aufgebaut ist, sehen Sie in Beispiel 10-3.
Der grundlegende Mechanismus für Client-Server-Anwendungen wird vom RPC-Paket (Remote Procedure Call) bereitgestellt. RPC wurde von Sun Microsystems entwickelt und ist eine Sammlung von Werkzeugen und Bibliotheksfunktionen. Eine wichtige Anwendung, die auf RPC aufsetzt, ist NFS.
Ein RPC-Server besteht aus einer Reihe von Prozeduren, die ein Client aufrufen kann, indem er eine RPC-Anforderung zusammen mit den Prozedurparametern an den Server schickt. Der Server führt die gewählte Prozedur im Namen des Clients aus und liefert das Ergebnis zurück, falls es eines gibt. Um maschinenunabhängig zu sein, werden alle zwischen dem Client und dem Server ausgetauschten Daten vom Sender in das so genannte XDR-Format (External Data Representation) umgewandelt und vom Empfänger wieder in die lokale Repräsentation der Maschine zurückübersetzt. RPC benutzt Standard-UDP- und -TCP-Sockets, um die XDR-formatierten Daten zum entfernten Host zu übertragen. Sun hat RPC großzügigerweise als Public Domain freigegeben. Es wird in einer Reihe von RFCs beschrieben.
Manchmal führen Verbesserungen an einer RPC-Anwendung zu inkompatiblen Veränderungen in der Schnittstelle der Prozeduraufrufe. Natürlich würde ein einfacher Austausch des Servers alle Anwendungen zum Absturz bringen, die noch das ursprüngliche Verhalten erwarten. Deshalb werden RPC-Programmen Versionsnummern zugewiesen, die normalerweise bei 1 beginnen und mit jeder neuen RPC-Version erhöht werden. Häufig kann ein Server mehrere Versionen gleichzeitig anbieten. Die Clients geben dann in ihren Anforderungen durch die Versionsnummer an, welche Implementierung des Dienstes sie benutzen wollen.
Die Kommunikation zwischen RPC-Servern und -Clients ist etwas eigenartig. Ein RPC-Server bietet eine oder mehrere Sammlungen von Prozeduren an; jede Sammlung wird als Programm bezeichnet und durch eine Programmnummer eindeutig identifiziert. Eine Liste, die Dienstnamen auf Programmnummern abbildet, wird für gewöhnlich in der Datei /etc/rpc gespeichert. Ein Ausschnitt davon ist in Beispiel 10-4 zu sehen.
In TCP/IP-Netzwerken wurden die Autoren von RPC mit dem Problem konfrontiert, Programmnummern auf allgemeine Netzwerkdienste abzubilden. Sie gestalteten jeden Server so, dass er für jedes Programm und jede Version sowohl einen TCP- als auch einen UDP-Port bereitstellt. Im Allgemeinen verwenden RPC-Anwendungen UDP, um Daten zu übertragen, und greifen nur dann auf TCP zurück, wenn die zu übertragenden Daten nicht in ein einzelnes UDP-Datagramm passen.
Natürlich müssen Client-Programme eine Möglichkeit haben, um herauszufinden, auf welchen Port eine Programmnummer abgebildet wird. Die Verwendung einer Konfigurationsdatei wäre für diesen Zweck zu unflexibel. Da RPC-Anwendungen keine reservierten Ports verwenden, gibt es keine Garantie, dass ein ursprünglich von unserer Datenbankanwendung zu benutzender Port nicht von einem anderen Prozess besetzt wurde. Darum nimmt eine RPC-Anwendung irgendeinen Port, den sie kriegen kann, und registriert ihn mit einem speziellen Programm, dem so genannten Portmapper-Dämon. Der Portmapper fungiert als Dienstvermittler für alle RPC-Server, die auf dieser Maschine laufen. Ein Client, der einen Dienst mit einer gegebenen Programmnummer kontaktieren möchte, fragt zuerst den Portmapper auf dem Host des Servers ab, der dann die TCP- und UDP-Portnummern zurückliefert, über die der Dienst erreicht werden kann.
Diese Methode hat den Nachteil, dass sie - genau wie inetd für die normalen Berkeley-Dienste - einen »single point of failure« darstellt. Nur ist dieser Fall sogar noch schlimmer, weil alle RPC-Port-Informationen verloren gehen, wenn der Portmapper seinen Geist aufgibt. Das bedeutet normalerweise, dass Sie alle RPC-Server manuell neu starten oder sogar die gesamte Maschine neu hochfahren müssen.
Unter Linux wird der Portmapper /sbin/portmap oder manchmal auch /usr/sbin/rpc.portmap genannt. Sie müssen lediglich sicherstellen, dass er von einem Ihrer Netzwerk-Boot-Skripten aus gestartet wird; ansonsten erfordert der Portmapper keine Konfiguration.
Häufig ist es sehr nützlich, einen Befehl direkt auf einem entfernten Host ausführen zu können und diesem Befehl sogar noch Ein- und Ausgaben über das Netzwerk zu ermöglichen.
Die traditionellen Befehle zum Ausführen von Befehlen auf entfernten Hosts sind rlogin, rsh und rcp. Über die damit einhergehenden Sicherheitsfragen haben wir in Kapitel 1 bereits kurz gesprochen und dabei ssh als Ersatz vorgeschlagen. Das ssh-Paket bietet die Ersatzbefehle ssh und scp.
Jeder dieser Befehle führt eine Shell auf dem entfernten Host aus und erlaubt dem Benutzer die Ausführung von Befehlen. Natürlich benötigt der Client einen Benutzerzugang auf dem Host, auf dem der Befehl ausgeführt werden soll. Folglich führen all diese Befehle einen Authentifizierungsvorgang durch. Die r-Befehle tauschen dazu zwischen den Hosts einfach die Benutzernamen und Kennwörter aus. Das geschieht ohne Verschlüsselung, so dass jeder leicht die Kennwörter abhören kann. Die ssh-Befehle dagegen bieten mehr Sicherheit. Sie benutzen dafür eine Technik, die als Public Key Cryptography (Verschlüsselung mit öffentlichem Schlüssel) bezeichnet wird. Sie bietet Authentifizierung und Verschlüsselung zwischen Hosts und stellt sicher, dass weder Kennwörter noch andere Daten von anderen Hosts leicht abgehört werden können.
Es ist möglich, die Authentifizierungsprüfungen für bestimmte Benutzer noch weiter zu lockern. Wenn Sie sich beispielsweise sehr häufig auf einer anderen Maschine in Ihrem LAN einloggen müssen, wollen Sie vielleicht auch direkten Zugriff erhalten, ohne jedes Mal Ihr Kennwort eingeben zu müssen. Mit den r-Befehlen war das schon immer möglich, aber die ssh-Suite macht Ihnen das noch etwas leichter. Das ist zwar immer noch keine gute Idee, denn wenn erst einmal ein Benutzerkonto geknackt wurde, kann man Zugriff auf alle anderen Benutzerkonten erlangen, die dieser Anwender für ein kennwortfreies Login konfiguriert hat. Trotz allem ist es eine bequeme Methode, und die Leute benutzen sie auch.
Lassen Sie uns nun darüber reden, wie Sie die r-Befehle über Bord werfen und stattdessen die ssh-Befehle nutzen.
Als Erstes entfernen wir alle r-Befehle, falls sie installiert sind. Der einfachste Weg, die alten r-Befehle zu deaktivieren, besteht darin, ihre Einträge in der Datei /etc/inetd.conf auszukommentieren (oder zu löschen). Die wichtigen Einträge dort sehen in etwa so aus:
Sie können diese Zeilen auskommentieren, indem Sie ein #-Zeichen an den Zeilenanfang schreiben, oder die Zeilen komplett löschen. Denken Sie daran, dass Sie den inetd-Dämon neu starten müssen, um diese Änderungen wirksam werden zu lassen. Am besten entfernen Sie auch die Dämonprogramme selbst aus Ihrem System.
OpenSSH ist eine freie Version der ssh-Software. Die Linux-Portierung ist über ftp://ftp.openbsd.org/unix/OpenBSD/OpenSSH/portable/ und die meisten modernen Linux-Distributionen erhältlich.3 Die Kompilierung werden wir hier nicht beschreiben; im Quellcode finden Sie entsprechende Anweisungen. Falls Ihnen das Programm in Form eines vorkompilierten Pakets zur Verfügung steht, sollten Sie es auch daraus installieren.
Eine ssh-Sitzung besteht aus zwei Komponenten. Zum einen gibt es einen ssh-Client, den Sie konfigurieren müssen und auf dem lokalen Host ausführen, zum anderen einen ssh-Dämon, der auf dem entfernten Host laufen muss.
Der sshd-Dämon ist ein Programm, das auf Netzwerkverbindungen von ssh-Clients achtet, die Authentifizierung erledigt und den gewünschten Befehl ausführt. Es benutzt eine Haupt-Konfigurationsdatei namens /etc/ssh/sshd_config sowie eine spezielle Datei, die einen Schlüssel enthält, der von den Authentifizierungs- und Verschlüsselungsprozessen benutzt wird, um den Rechner selbst zu repräsentieren. Jeder Server und jeder Client hat seinen eigenen Schlüssel.
Den Distributionen liegt ein Dienstprogramm namens ssh-keygen bei, mit dem sich zufällige Schlüssel erzeugen lassen. Das wird normalerweise nur einmal während der Installation gemacht, um den Hostschlüssel zu bilden, den der Systemadministrator für gewöhnlich in der Datei /etc/ssh/ssh_host_key ablegt. Die Schlüssel können beliebig lang sein, ab 512 Bits und mehr. Standardmäßig erzeugt ssh-keygen Schlüssel mit einer Länge von 1024 Bits, was auch von den meisten Anwendern übernommen wird. Wenn Sie OpenSSH mit SSH Version 2 benutzen, müssen Sie RSA- und DSA-Schlüssel erzeugen. Um die Schlüssel zu erzeugen, rufen Sie ssh-keygen folgendermaßen auf:
Sie werden aufgefordert, eine Passphrase einzugeben, falls Sie die Option -N weggelassen haben. Hostschlüssel benötigen jedoch keine Passphrase, so dass Sie hier einfach die Return-Taste drücken können. Die Programmausgabe sieht dann etwa so aus:
Wahrscheinlich haben Sie bemerkt, dass drei unterschiedliche Schlüssel angelegt wurden. Der erste, Typ rsa1, wird für das SSH-Protokoll Version 1 verwendet, die beiden nächsten Typen, rsa und dsa, werden für das SSH-Protokoll Version 2 benutzt. Es wird empfohlen, wegen der Gefahr von Man-in-the-Middle- und anderen Angriffen SSH-Protokoll Version 2 anstelle von SSH-Protokoll Version 1 einzusetzen.
Am Ende haben Sie zwei erzeugte Dateien vor sich. Der erste Schlüssel wird als privater Schlüssel bezeichnet, der geheim gehalten werden muss und in /etc/openssh/ssh_host_key aufbewahrt wird. Der zweite wird als öffentlicher Schlüssel bezeichnet und ist derjenige, den Sie mit anderen gemeinsam benutzen können; er wird in /etc/openssh/ssh_host_key.pub abgelegt.
Nachdem Sie mit den Schlüsseln für die ssh-Kommunikation ausgestattet sind, müssen Sie noch eine Konfigurationsdatei erzeugen. Die ssh-Software ist sehr leistungsfähig, und die Konfigurationsdatei kann daher viele Optionen enthalten. Zur Einführung präsentieren wir Ihnen ein kleines Beispiel. Um die anderen Funktionen zu aktivieren, sollten Sie in der ssh-Dokumentation nachlesen. Der folgende Code zeigt eine sichere und minimale sshd-Konfigurationsdatei. Die weiteren Konfigurationsoptionen werden ausführlich in der Manpage sshd(8) beschrieben:
Sie sollten auf jeden Fall überprüfen, ob die Zugriffsrechte der Konfigurationsdateien korrekt eingestellt sind, um sicherzustellen, dass die Systemsicherheit gewährleistet ist. Führen Sie dazu folgende Anweisungen aus:
Der letzte Schritt in der Administration des sshd-Dämons besteht nur noch darin, ihn zum Laufen zu bringen. Normalerweise würden Sie dazu eine rc-Datei erzeugen oder ihn in eine existierende Datei eintragen, so dass er beim Systemstart automatisch ausgeführt wird. Der Dämon läuft eigenständig und braucht keinen Eintrag in der Datei /etc/inetd.conf. Der Dämon muss als root laufen. Die Syntax ist sehr einfach:
Der sshd-Dämon versetzt sich beim Start automatisch in den Hintergrund. Nun sind Sie in der Lage, ssh-Verbindungen zu akzeptieren.
Es gibt eine Reihe von ssh-Client-Programmen: slogin, scp und ssh. Sie alle lesen dieselbe Konfigurationsdatei ein, für gewöhnlich /etc/openssh/ssh_config. Außerdem lesen sie Konfigurationsdateien aus dem Verzeichnis .ssh im Home-Verzeichnis des Benutzers, der sie ausführt. Die wichtigsten dieser Dateien sind .ssh/config, die Optionen enthalten kann, die die in der Datei /etc/openssh/ssh_config enthaltenen Optionen überschreiben, außerdem .ssh/identity, die den benutzereigenen privaten Schlüssel enthält, und die entsprechende Datei .ssh/identity.pub mit dem öffentlichen Schlüssel des Benutzers. Weitere wichtige Dateien sind .ssh/known_hosts und .ssh/authorized_keys. Über sie sprechen wir im nächsten Abschnitt »ssh anwenden«. Zunächst erzeugen wir die globale Konfigurationsdatei und die Schlüsseldatei des Benutzers.
Die Datei /etc/ssh/ssh_config ist der Server-Konfigurationsdatei sehr ähnlich. Auch hier gibt es viele Funktionen, die Sie konfigurieren können. Eine minimale Konfigurationsdatei hat die in Beispiel 10-5 gezeigte Form. Die restlichen Konfigurationsoptionen werden detailliert in der Manpage sshd(8) beschrieben. Sie können Abschnitte hinzufügen, die zu bestimmten Hosts oder Gruppen von Hosts passen. Der Parameter für die Host-Anweisung kann entweder der vollständige Name eines Hosts oder ein Wildcard-Ausdruck sein, wie wir es in unserem Beispiel gemacht haben, um alle Hosts auszuwählen. Wir könnten zum Beispiel einen Eintrag wie Host *.vbrew.com erzeugen, der zu jedem Host in der Domain vbrew.com passt.
Im Abschnitt über die Serverkonfiguration erwähnten wir, dass jeder Host und jeder Benutzer einen Schlüssel hat. Der Benutzerschlüssel wird in dessen ~/.ssh/identity-Datei gespeichert. Zur Erzeugung des Schlüssels benutzen Sie denselben ssh-keygen-Befehl, den wir auch zur Erzeugung des Hostschlüssels verwendet haben; nur müssen Sie diesmal nicht den Namen der Datei angeben, in der Sie den Schlüssel aufbewahren wollen. ssh-keygen gibt dafür die richtige Voreinstellung an, fragt aber trotzdem nach, ob Sie einen anderen Dateinamen wünschen. Manchmal ist es sinnvoll, mehrere identity-Dateien zu haben, weshalb ssh dies auch gestattet. Wie vorher fordert ssh-keygen Sie auf, eine Passphrase einzugeben. Passphrasen tragen zur Erhöhung der Sicherheit bei und sind somit eine gute Sache. Ihre Passphrase wird bei der Eingabe nicht auf dem Bildschirm angezeigt.
Sie sollten jeden Ihrer Benutzer auffordern, den Befehl ssh-keygen nur einmal auszuführen, um sicherzustellen, dass seine Schlüsseldatei korrekt angelegt wird. Der Befehl erzeugt für sie ein ~/.ssh/-Verzeichnis mit den entsprechenden Zugriffsrechten und ihre privaten bzw. öffentlichen Schlüssel in .ssh/identity bzw. .ssh/identity.pub. Eine Beispielsitzung sieht etwa so aus:
Nun kann man mit ssh loslegen.
Inzwischen sollten wir ssh und seine zugehörigen Programme installiert und betriebsbereit haben. Lassen Sie uns einen kurzen Blick darauf werfen, wie man sie anwendet.
Als Erstes versuchen wir, uns an einem entfernten Host anzumelden. Beim ersten Versuch, eine Verbindung mit einem Host herzustellen, empfängt der ssh-Client den öffentlichen Schlüssel vom Host und fordert Sie auf, seine Identität zu bestätigen, indem er Ihnen eine Kurzform dieses Schlüssels ausgibt, die als »Fingerabdruck« bzw. Fingerprint bezeichnet wird.
Der Administrator des entfernten Hosts sollte Ihnen bereits vorsorglich den Fingerprint des öffentlichen Schlüssels mitgeteilt haben. Diesen sollten Sie Ihrer Datei .ssh/known_hosts hinzufügen. Haben Sie dagegen noch keinen Fingerprint bekommen, können Sie sich trotzdem mit dem entfernten Host verbinden, jedoch warnt ssh Sie mit dem Hinweis, dass dieser Host einen Schlüssel hat, und fragt Sie, ob Sie den Schlüssel vom entfernten Host akzeptieren wollen. Wenn Sie sicher sind, dass niemand gerade ein DNS-Spoofing bei Ihnen durchführt und Sie tatsächlich mit dem richtigen Host kommunizieren, beantworten Sie die Frage mit »yes«. Der relevante Schlüssel wird dann automatisch in Ihrer .ssh/known_hosts-Datei vermerkt, und Sie werden in Zukunft nicht mehr danach gefragt. Wenn Sie irgendwann wieder eine Verbindung aufbauen und der vom Host empfangene öffentliche Schlüssel nicht mit dem gespeicherten übereinstimmt, werden Sie gewarnt, da hier eine potenzielle Sicherheitsverletzung vorliegt.
Das erstmalige Login an einem entfernten Host geht etwa so vor sich:
Sie werden nach einem Kennwort gefragt. Hier sollten Sie das Kennwort für den entfernten Benutzerzugang eingeben, nicht das für den lokalen Zugang. Das Kennwort wird bei der Eingabe nicht angezeigt.
Sind keine besonderen Argumente angegeben, versucht ssh einen Login mit derselben Benutzer-ID wie auf der lokalen Maschine. Mit der Option -l können Sie das überschreiben und einen alternativen Login-Namen für den entfernten Host angeben. Genau das haben wir in einem früheren Beispiel in diesem Buch getan. Alternativ können Sie mit dem Format benutzerid@hostname.ext einen anderen Benutzernamen festlegen.
Dateien zum bzw. vom entfernten Host können wir mit dem Programm scp kopieren. Die Syntax gleicht der des konventionellen cp-Befehls mit der Ausnahme, dass Sie vor einem Dateinamen auch einen Hostnamen angeben können, was bedeutet, dass sich die Datei auf dem genannten Host befindet. (Es ist auch möglich, das bereits erwähnte benutzerid@ hostname-Format zu benutzen.) Das folgende Beispiel illustriert die scp-Syntax, indem eine lokale Datei namens /tmp/fred nach /home/maggie/ auf dem entfernten Host vlager.vbrew.com kopiert wird:
Auch hier werden Sie nach einem Kennwort gefragt. Der Befehl scp zeigt standardmäßig nützliche Informationen über den Stand des Dateitransfers an. Genauso einfach kopieren Sie eine Datei von einem entfernten Host. Dazu geben Sie einfach nur einen Hostnamen und ein Verzeichnis als Quelle sowie den lokalen Pfad als Ziel an. Es ist sogar möglich, eine Datei von einem entfernten Host auf einen anderen entfernten Host zu kopieren. Allerdings würde man so etwas normalerweise nicht machen, da die gesamten Daten den Umweg über Ihren Host nehmen müssen.
Mit ssh können Sie Befehle auf entfernten Hosts ausführen. Auch hier ist die Syntax sehr einfach. Nehmen wir an, die Benutzerin maggie will sich das Wurzelverzeichnis auf dem entfernten Host vchianti.vbrew.com ansehen. Das kann sie folgendermaßen tun:
Sie können ssh auch in eine Befehls-Pipeline setzen und damit Ein-/Ausgabeumleitungen durchführen wie mit allen anderen Befehlen auch, mit der Ausnahme, dass die Ein- bzw. Ausgabe vom bzw. zum entfernten Host über die ssh-Verbindung erfolgt. Das folgende Beispiel zeigt, wie Sie diese Möglichkeit mit dem Befehl tar kombinieren können, um ein komplettes Verzeichnis inklusive aller Unterverzeichnisse und Dateien von einem entfernten auf den lokalen Host zu kopieren:
In diesem Beispiel haben wir die auszuführende Anweisung in Anführungszeichen gesetzt, um festzulegen, was als Argument an ssh übergeben wird und was von der lokalen Shell verarbeitet werden soll. Diese Anweisung startet das Programm tar auf dem entfernten Host, archiviert das Verzeichnis /etc/ und gibt das Archiv auf der Standardausgabe aus. Diese Ausgabe leiten wir auf die Standardeingabe eines lokalen tar-Befehls um, der das Archiv auf der lokalen Maschine wieder entpackt.
Wiederum werden wir nach dem Kennwort gefragt. Wir wollen unseren lokalen ssh-Client jetzt so konfigurieren, dass er nicht nach einem Kennwort fragt, wenn wir eine Verbindung zu vchianti.vbrew.com herstellen. Wir erwähnten bereits die Datei .ssh/authorized_keys, sie kommt hier ins Spiel. Die Datei .ssh/authorized_keys enthält die öffentlichen Schlüssel für alle entfernten Benutzerkonten, an denen wir uns automatisch anmelden wollen. Sie können die automatischen Logins aktivieren, indem Sie den Inhalt der Datei .ssh/identity.pub vom entfernten Zugang in Ihre lokale .ssh/authorized_keys-Datei kopieren. Achten Sie unbedingt darauf, dass die Zugriffsrechte von .ssh/authorized_keys so gesetzt sind, dass nur Sie darin lesen und schreiben können, damit nicht andere die Schlüssel stehlen und sich damit auf dem entfernten Host anmelden können. Um sicherzugehen, dass die Zugriffsrechte korrekt eingestellt sind, setzen Sie sie für .ssh/authorized_keys folgendermaßen:
Die öffentlichen Schlüssel bestehen aus einer einzelnen langen Klartextzeile. Wenn Sie einen solchen Schlüssel mittels Copy-and-Paste in Ihre lokale Datei übertragen, stellen Sie sicher, dass Sie nicht versehentlich irgendwelche anderen Zeichen (z.B. Zeilenwechsel) mit übernehmen. Die Datei .ssh/authorized_keys kann viele Schlüssel enthalten, jeden davon in einer eigenen Zeile.
Die ssh-Software ist sehr leistungsfähig und bietet noch viele andere nützliche Funktionen und Optionen, die Sie vielleicht kennen lernen wollen. Mehr Informationen finden Sie in den Manpages und in anderen Dokumentationen, die mit der Software geliefert werden.
© 2005, O'Reilly Verlag GmbH & Co. KG