SSH steht für Secure Shell. SSH ist ein Protokoll für verschlüsselte Login-Verbindungen auf andere Rechner. SSH stellt die Kommandozeile eines entfernten Rechners lokal zur Verfügung. Dadurch ist SSH ein wichtiger Netzwerkdienst für die Fernverwaltung von Linux-/Unixrechnern. SSH kann jedoch noch mehr als nur auf die Kommandozeile eines entfernten Rechners zu verbinden: SSH kann auch Dateien über das Netzwerk kopieren, grafische Fenster des entfernten Rechners anzeigen und andere Netzwerkverbindungen durch einen verschlüsselten Tunnel transportieren. SSH wird inzwischen fast nur noch in seiner OpenSource-Variante als OpenSSH verwendet, welches vom OpenBSD Projekt entwickelt wird.
SSH wurde als sicherer Ersatz für Remote Login Protokolle wie rsh und Telnet entwickelt. Um die Sicherheit zu gewährleisten muß neben der Verschlüsselung auch eine Man in the Middle Attacke verhindert werden.
Ein SSH-Client nimmt mit einem SSH-Server eine Verbindung auf (schwarze Pfeile). Dazu fragt der SSH-Client zunächst einen DNS-Server nach der IP-Adresse des SSH-Servers und nimmt dann eine verschlüsselte Verbindung auf. Ein Angreifer hat keine Chance die verschlüsselte Verbindung zu belauschen.
Ein findiger Angreifer könnte nun aber auf folgende Idee kommen: Wenn ich die Verbindung die über das Netzwerk geht schon nicht belauschen kann, dann kann ich einfach versuchen, mich selbst als den gewünschten SSH-Server auszugeben, so das die Verbindung zu mir geleitet wird und ich alle gewünschten Daten bekomme. Dies ist dann ein Man in the middle Angriff. Dieser kann z. B. so aussehen (grüne Pfeile): Der SSH-Client möchte wieder eine Verbindung mit dem SSH-Server aufnehmen. Dazu befragt er wieder einen DNS-Server nach der gewünschten Adresse (1). Anstatt des DNS-Servers kann nun der Angreifer eine gefälschte DNS-Antwort schicken (2). In der gefälschten DNS-Antwort gibt der Angreifer sich als der gewünschte Server aus. Der SSH-Client baut daraufhin die SSH-Verbindung mit dem Angreifer, anstatt mit dem gewünschten Server auf (3). Damit der Client keinen Verdacht schöpft, baut der Angreifer zusätzlich eine SSH-Verbindung zum Server auf und leitet alle vom Client empfangenen Daten weiter (4). Der Angreifer sitzt nun als Proxy in der Mitte zwischen Client und dem wirklichen Server und kann alle Datenpakete belauschen, obwohl diese verschlüsselt über die Leitung gehen.
Um genau solche Angriffe zu verhindern, benutzt SSH Hostschlüssel. Beim ersten Starten eines SSH-Servers werden diese Hostschlüssel generiert. Loggt sich ein Client auf dem Server zum ersten mal ein, wird der sogenannte Fingerprint des Hostschlüssels angezeigt und nachgefragt ob dieser Hostschlüssel akzeptiert werden soll. Bejaht man dies, wird der Hostschlüssel auf dem Client abgespeichert. Bei jedem zukünftigen Login-Versuch wird nun der gespeicherte Hostschlüssel mit dem vom Server angegebenen verglichen. Stimmmen diese nicht überein, meldet der Client mit einer deutlichen Warnmeldung einen Man in the middle Angriff und bricht die Verbindung ab.
Beim ersten Login-Versuch kann man entweder einfach darauf vertrauen, das alles stimmt, oder sicherer, den angegebenen Fingerprint des Hostschlüssels auf Richtigkeit überprüfen. Dazu kann man diesen entweder vorher aufgeschrieben haben oder aber man ruft den Administrator des Servers an und läßt sich den Fingerprint telefonisch durchgeben. Den Fingerprint eines Hostschlüssels kann man sich mit dem Befehl ssh-keygen anzeigen lassen. Die Hostschlüssel eines Servers sind gespeichert unter /etc/ssh, als ssh_host_rsa_key und ssh_host_dsa_key. DSA und RSA sind 2 verschiedene Verschlüsselungsalgorithmen. Der Fingerprint des RSA-Hostschlüssels kann also so angezeigt werden:
ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
Der Parameter -l dient bei ssh-keygen zur Anzeige des Fingerprints eines Schlüssels, der Parameter -f gibt die Schlüsseldatei an. Auf dem Client wird der Schlüssel in der Datei ~/.ssh/known_hosts gespeichert, wobei jede Zeile dieser Datei für einen Server steht. Sollte sich mal ein Hostschlüssel eines Servers aus legitimen Gründen (z. B. weil der Server neu installiert wurde und dadurch der Hostschlüssel neu erzeugt wurde) ändern, muß man auch die entsprechende Zeile in der ~/.ssh/known_hosts löschen um eine Warnmeldung beim nächsten Login zu vermeiden.
Nach dieser Sicherheitstheorie nun direkt zur Verwendung von SSH: Um sich auf einen entfernten Rechner per SSH einzuloggen, gibt man einfach das Kommando ssh gefolgt vom Rechnernamen an:
ssh server.domain
In diesem Fall wird als Loginname der gleiche Benutzername wie lokal verwendet. Weicht der lokale Benutzername von dem Benutzernamen, den man auf dem entfernten Server hat ab, kann man die Schreibweise user@host verwenden:
ssh benutzer@server.domain
Beim ersten Login, wird wie bereits oben erwähnt der Hostschlüssel des entfernten Servers angezeigt und dieser muß bestätigt werden. Bei allen weiteren Logins wird der Hostschlüssel automatisch im Hintergrund überprüft. Danach wird das Passwort des Benutzers auf dem Server verlangt und man ist eingeloggt. Nun kann man auf der Kommandozeile des entfernten Rechners arbeiten, ganz genau so als säße man davor.
Auch Dateien lassen sich per SSH zwischen 2 Rechnern austauschen. Dazu gibt es sogar gleich 2 Möglichkeiten: scp und sftp. scp ist als Kommandozeilenwerkzeug dem Kommando cp nachgebildet, nur das es Dateien per SSH im Netzwerk kopiert. Möchte man z. B. die Datei meintext.txt vom lokalen Rechner auf den Server meinserver kopieren kann das so aussehen:
scp meintext.txt benutzer@meinserver:
In diesem Fall wird die Datei direkt in das Heimatverzeichnis des Benutzers auf dem entfernten Server gelegt. Generell ist die Syntax von scp: scp Quelle Ziel, wobei der entfernte Rechner sowohl Quelle als auch Ziel sein kann. Der Dateiort auf dem entfernten Rechner wird immer mit benutzer@host:verzeichnis angegeben. Wobei der Benutzername auch weggelassen werden kann, falls er sich nicht vom lokalen unterscheidet. Der Doppelpunkt trennt den Hostnamen von der Pfadangabe. Pfadangaben können entweder relativ zum Heimatverzeichnis sein (wenn der führende Schrägstrich weggelassen wird) oder als absoluter Pfad (mit führenden Schrägstrich). Ein anderes Beispiel für einen scp Befehl:
scp benutzer@server:/etc/hosts .
In diesem Fall wird die Datei /etc/hosts des entfernten Servers lokal in das momentane Arbeitsverzeichnis kopiert.
Die andere Alternative für Dateitransfers ist sftp. sftp ist ein moderner verschlüsselt arbeitender Ersatz für FTP. Dabei lehnt sich die Bedienung zwar an FTP an, das verwendete Protokoll ist aber SSH. sftp ist also nicht die verschlüsselte Variante von FTP, sondern die FTP-artige Variante von SSH.
sftp wird gestartet wie ein SSH-Login:
sftp benutzer@host
Danach bekommt man (nach Eingabe seines Passworts) einen sftp-Prompt, an dem man FTP-artige Kommandos eingeben kann. Eine Übersicht über die verfügbaren Kommandos bekommt man mit dem Kommando "help". Mit dem Kommando "put" kann man z. B. Dateien heraufladen. Mit dem Kommando "quit" verläßt man den sftp-Prompt wieder und beendet die Verbindung. Es gibt auch einige grafische FTP-Programme die das sftp-Protokoll verstehen.
Neben der Authentifizierung durch Passwörter, kennt SSH auch eine schlüsselbasierte Authentifizierung. Diese beruht auf dem Public-/Private-Key Verfahren (asymetrische Kryptografie). Durch die Verwendung der schlüsselbasierten Authentifizierung kann sowohl die Sicherheit, als auch der Komfort beim anmelden erhöht werden.
Um schlüsselbasierte Authentifizierung zu verwenden, muß man als erstes ein Schlüsselpaar erzeugen. Der Befehl hierfür heißt ssh-keygen:
ssh-keygen -t rsa
Dieser Befehl erzeugt ein RSA-Schlüsselpaar und fragt nach dem Speicherort (bei dem man den Default übernehmen sollte), sowie nach einer Passphrase. Sofern man den Defaultspeicherplatz für das Schlüsselpaar übernimmt, findet man danach das neu erzeugte Schlüsselpaar unter ~/.ssh/id_rsa (privater Schlüssel) und ~/.ssh/id_rsa.pub (öffentlicher Schlüssel). Schlüsselbasierte Authentifizierung funktioniert so das sich nur der Besitzer des privaten Schlüssels (der unbedingt geheim zu halten ist) an einem Server anmelden kann, auf dem der öffentliche Schlüssel hinterlegt ist. Was hat es mit der Passphrase auf sich? Die Passphrase schützt den privaten Schlüssel zusätzlich. Mit der Passphrase wird der private Schlüssel auf der Festplatte verschlüsselt. Dadurch kann man den privaten Schlüssel nur noch nach Eingabe der Passphrase benutzen. Ohne Passphrase kann jeder der in den Besitz des privaten Schlüssels kommt diesen auch direkt zum Login benutzen. Gibt man bei der Frage nach der Passphrase bei der Schlüsselerzeugung nichts an, wird der Schlüssel auch ohne Passphrase angelegt. Mit solch einen Schlüssel muß man beim Login keine Passphrase mehr angeben (was bequem ist), aber sicherer ist es eine Passphrase zu benutzen. Zumindest wenn man seinen privaten Schlüssel auf mobilen Geräten, wie Notebooks oder USB-Sticks hinterlegt, sollte dieser in jedem Fall mit einer Passphrase geschützt werden, da solche Geräte auch gestohlen werden können oder verloren gehen können. Passphrasenlose Schlüssel sind hingegen praktisch um automatische Logins aus Cronjobs heraus auszuführen, z. B. in Backupjobs.
Zusammengefaßt kann man sagen, das ein Passphrasenloser Schlüssel den Komfort erhöht (keine Passworteingabe mehr) aber neue, bzw. andere Sicherheitsimplikationen mit sich bringt. Ein durch eine Passphrase geschützter Schlüssel kann die Sicherheit erhöhen, da man dann einen SSH-Server so einstellen kann, das er nur noch Anmeldungen mit Schlüssel akzeptiert und ein in falsche Hände geratenes Passwort keinen Login mehr ermöglicht. Ich werde gleich auch noch zeigen, wie man selbst unter Verwendung von durch Passphrase geschützten Schlüsseln einen bequemen passwortlosen Login ermöglichen kann (was maximale Sicherheit mit Komfort verbindet).
Um nun schlüsselbasierte Anmeldung verwenden zu können, muß noch der öffentliche Schlüssel des neu erzeugten Schlüsselpaares auf den Server übertragen werden. Dies kann per scp oder sftp erfolgen. Hat man seinen Schlüssel (z. B. id_rsa.pub) übertragen muß man ihn auf dem Server unter einen bestimmten Namen speichern, damit er auch als SSH-Anmeldeschlüssel erkannt wird. Auf dem Server muß man den Schlüssel daher in der Datei ~/.ssh/authorized_keys speichern. Existiert die Datei noch nicht kann man seinen öffentlichen Schlüssel einfach entsprechend umbenennen:
mv id_rsa.pub ~/.ssh/authorized_keys
Diese Datei kann auch mehrere Schlüssel enthalten, jeweils einen pro Zeile. Hat man also mehrere Clients von denen man sich auf diesen Server aus anmeldet, kann man auf jeden Client einen Schlüssel erzeugen und in die Datei mit aufnehmen. Existiert die Datei bereits und enthält schon einen Schlüssel, könnte eine zusätzlicher Schlüssel also z. B. so hinzugefügt werden:
cat id_rsa.pub >> ~/.ssh/authorized_keys
Wichtig bei diesem Befehl, ist das doppelte >>, welches den Inhalt der ersten Datei an die existierende Datei anhängt, statt sie zu überschreiben.
Eine besonders angenehme Sache in Verbindung mit der schlüsselbasierten Authentifizierung ist der SSH-Agent. Über den SSH-Agenten ist es mögliche eine Passphrase für einen durch Passphrase geschützten Schlüssel im Arbeitsspeicher zu behalten, nach dem er einmal eingegeben wurde. Dies ermöglicht Passwortlose Logins trotz Verwendung von durch Passphrase geschützten Schlüsseln. Der SSH-Agent wird durch das Kommando ssh-agent gestartet. Es gibt 2 Möglichkeiten dies zu tun: Der SSH-Agent benötigt immer einen Prozess mit dem zusammen er läuft, beendet sich der Prozess, dann beendet sich auch der SSH-Agent. Innerhalb des mit dem SSH-Agent gestarteten Prozesses, muß dann mit dem Befehl ssh-add, die Passphrase nur einmal eingegeben werden und für alle danach stattfindenden Logins bleibt die Passphrase im Speicher. Daher sollte der zusammen mit dem SSH-Agent gestartete Prozess eine Shell oder z. B. eine X-Sitzung sein, damit alle in dieser Shell oder innerhalb dieser X-Sitzung gestarteten Programme (wie eben der SSH-Client) auf den SSH-Agent zugreifen können. Die anderen Prozesse (wie etwa ein Xterm, eine Shell oder eine ganze X-Sitzung) sind dann ein Kindprozess des SSH-Agenten. Dies ist allerdings unpraktisch wenn man bereits eine Shellsitzung offen hat, die noch kein Kindprozess des SSH-Agenten ist. Man könnte dann natürlich auch einfach eine neue Shell starten:
ssh-agent bash
Praktischer ist es jedoch in so einem Fall in der bereits existierenden Shell einen SSH-Agenten zu starten. Dies läßt sich mit folgenden Befehl erreichen:
eval `ssh-agent -s`
Dieser Befehlt führt den ssh-agent aus und gibt über den Parameter -s gleich ein paar Variablen passend für Bourne-Shell kompatible Shells aus (also z. B. für ksh, bash und zsh). Diese Variablen werden durch das eval gleich geparst. Der Befehl eval wird dazu benutzt Ausgaben von Kommandos direkt als Befehle zu interpretieren.
Die meisten Linuxdistributionen und auch z. B. OpenBSD konfigurieren X-Sitzungen generell so, das bei vorhandensein von SSH-Schlüsseln X über den SSH-Agenten gestartet wird. Daher ist bei Verwendung einer X-Sitzung meist gar nichts mehr nötig um den SSH-Agenten zu starten. Um dann die Passphrasen für die Schlüssel auch in den Arbeitsspeicher zur Verwendung zu laden muß noch das Kommando ssh-add benutzt werden:
ssh-add
Das Kommando fragt dann nach der Passphrase. Einmal eingegeben steht diese dann so lange zur Verfügung wie der ssh-agent läuft (also im allgemeinen so lange wie man die Sitzung offen hält). SSH-Logins erfolgen dann ohne Eingabe eines Passwortes.
Alle geladenen Schlüssel bekommt man über folgendes Kommando angezeigt:
ssh-add -l
Über
ssh-add -D
lassen sich alle SSH-Identitäten wieder löschen. Dies erfolgt jedoch mit Beendigung des ssh-agent ohnehin automatisch und muß daher meist nicht extra gemacht werden.
Portforwarding und X-Forwarding sind 2 weitere recht interessante Möglichkeiten von SSH. Mit X11-Forwarding lassen sich grafische Programme auf anderen Rechnern aufrufen und deren Fenster lokal anzeigen.
Bei dieser Möglichkeit muß jedoch auf eine mögliche Sicherheitslücke hingewiesen werden: Jemand der auf den entfernten Rechner root-Rechte hat, kann bei aktivierten X11-Forwarding auf den laufenden X-Server meines lokalen Rechners zugreifen und dadurch z. B. Screenshots meines Bildschirms anfertigen und Tastatureingaben aufzeichnen. X11-Forwarding sollte daher nur zu vertrauenswürdigen Servern benutzt werden, bzw. zu Rechnern auf denen nur vertrauenswürdige Personen root-Rechte haben oder man selber als einzigster root-Rechte hat.
OpenSSH unterscheidet daher auch in neueren Versionen 2 verschiedene X11-Forwardings: Trusted X11 Forwarding, welches vollen Zugriff auf den X-Server gewährt und untrusted X11-Forwarding bei dem ein neues X-Authentifizierungs-Cookie erstellt wird, so das auf im gleichen X-Server laufende andere Programme nicht zugegriffen werden kann. Leider machen jedoch sehr viele grafische Programme Probleme im untrusted Modus, bzw. funktionieren gar nicht. Daher muß man meistens ohnehin das trusted X11 Forwarding benutzen.
ssh -Y benutzer@server
Mit dem Parameter -Y (großes Y) wird eine trusted X11-Forwarding Verbindung aufgebaut. Damit dies funktioniert muß auch auf dem Server in der Konfiguration des SSH-Servers X11-Forwarding aktiviert sein. Die Serverkonfiguration werde ich etwas weiter unten noch besprechen. Mit dem Parameter -X (großes X) anstatt -Y wird untrusted X11-Forwarding benutzt. In älteren SSH-Versionen war -X noch generell der Parameter für X11 Forwarding.
Hat man eine SSH-Verbindung mit X11 Forwarding zu einem Server aufgebaut, kann man auf der Shell grafische Programme starten. Die Fenster der Programme erscheinen dann auf dem eigenen lokalen X-Server. Zum aufrufen grafischer Programme muß übrigens, auf dem entfernten Rechner selbst, kein vollständiges X installiert haben oder der X-Server selber laufen. Es genügt wenn die entsprechenden X-Bibliotheken installiert sind.
Wesentlich genereller als X11 Forwarding ist das lokale Portforwarding. Beim lokalen Portforwarding lassen sich beliebige TCP-Ports von der lokalen Maschine durch die SSH-Verbindung hindurch zum entfernten Rechner durchleiten. Es entsteht also ein verschlüsselter Tunnel, den andere Anwendungen benutzen können. Quasi ein "arme Leute VPN". Interessant ist dies vor allem wenn man Netzwerkverbindungen verschlüsseln möchte, die sonst unverschlüsselt über die Leitung laufen würden. Auch Firewalls kann man damit umgehen, wenn die Firewall zwar SSH-Verbindungen erlaubt, aber andere Verbindungen nicht. In diesem Fall transportiert man die anderen Verbindungen durch die SSH-Verbindung mit.
ssh -L 8000:localhost:80 benutzer@server
Dieser Befehl bewirkt das man sich auf server als Benutzer benutzer einloggt und zusätzlich wird ein Portforwarding aktiviert. Der Parameter -L aktiviert das Portforwarding. Die Syntax dahinter bedeutet: lokaler Port:entfernter Rechner:entfernter Port. Der lokale Port ist der Port der auf der lokalen Maschine geöffnet wird. Alles was an diesen lokalen Port gesendet wird, wird durch den SSH-Tunnel weitergeleitet. Entfernter Rechner meint den Rechner zu dem die Verbindung weiter geleitet wird, dies kann, muß aber nicht der selbe Rechner sein wie der auf dem man sich einloggt. Handelt es sich um den gleichen Rechner gibt man am besten localhost an. Handelt es sich um einen anderen Rechner (der vom Rechner auf dem man sich eingeloggt hat erreichbar ist) gibt man dessen Hostnamen an. In diesem Fall läuft die Verbindung bis zum Loginrechner durch den SSH-Tunnel und ab dort ohne SSH-Tunnel weiter bis zum Zielrechner. Der entfernte Port, ist der Port auf dem auf dem entfernten Rechner ein entsprechender Dienst auf ankommende Anfragen lauscht. In diesem Beispiel wird also der lokale Port 8000 auf den entfernten Port 80 weitergeleitet. Sollte also auf dem entfernten Rechner auf Port 80 ein Webserver lauschen, würde man vom lokalen Rechner aus, durch Eingabe der Adresse http://localhost:8000 den entfernten Webserver durch den SSH-Tunnel erreichen.
Hat man SSH-Zugriff auf einen Firewall-Rechner kann man damit z. B. auch Dienste auf Hosts erreichen, die ansonsten durch die Firewall nicht erreichbar wären. Die Vorraussetzung dafür ist lediglich das es sich um TCP-Verbindungen mit einem einzelnen Port handelt (FTP ist z. B. ein 2 Port Protokoll). Ich habe selber bereits Portforwarding genutzt um Firewalls zu umgehen und auch um Verbindungen in unverschlüsselten Wlans abzusichern.
Ein Problem bleibt jedoch mit dem Portforwarding: Nehmen wir an ich surfe in einem unverschlüsselten Wlan. Ich habe die Möglichkeit für ein SSH-Login auf einem Server außerhalb des Wlans. Ich möchte meine Verbindung zum surfen durch einen verschlüsselten Tunnel leiten. Speziell beim surfen habe ich jedoch das Problem, das der Zielrechner immer mal wieder ein anderer ist. Ich müßte also ständig das Portforwarding ändern. Außerdem weiß das Portforwarding auch nichts von namensbasierten virtuellen Webhosts, mit dem verschiedene Websites auf einem Server erreicht werden können. Für genau solche Fälle ist das dynamische Portforwarding ideal. Dynamisches Portforwarding arbeitet wie ein Proxy mit angehängten SSH-Tunnel. Aktiviert man dynamisches Port-Forwarding erstellt der SSH-Client auf dem eigenen Rechner einen Socks-Proxy der auf eingehende Verbindungen lauscht. Jede eingehende Verbindung wird durch den SSH-Tunnel geleitet und am Endpunkt des Tunnels einfach an sein eigentliches Ziel weiter geschickt. Ein Socks-Proxy ist ein generischer TCP-Proxy, der alle Arten von Verbindungen weiterleiten kann (also nicht wie ein HTTP-Proxy nur auf HTTP-Verbindungen spezialisiert ist).
ssh -D 3200 benutzer@server
Mit dem Parameter -D (großes D) wird dynamisches Portforwarding aktiviert. Dahinter muß der Port angegeben werden auf dem lokal der Socks-Proxy lauscht. In meinem Browser muß ich nun lediglich in der Proxy-Konfiguration angeben, das der Browser einen Socks-Proxy auf localhost mit dem angegeben Port (im Beispiel 3200) benutzen soll. Achten sie darauf, das wenn sie ohne root-Rechte arbeiten sie nur Ports oberhalb 1024 öffnen können. Das jeweils benutzte Clientprogramm muß, um dies nutzen zu können, lediglich die Fähigkeit haben einen Socks-Proxy zu nutzen. Nicht alle Netzwerkprogramme können das. Von den Browsern ist Firefox z. B. dazu in der Lage, Opera leider nicht. Als Instant Messenger kann Pidgin, mit dem ich bereits Jabber-Verbindungen durch dynamisches Portforwarding genutzt habe, mit Socks-Proxys umgehen.
Das Agent-Forwarding ist ein weitere Möglichkeit des Forwardings mit SSH. Agent-Forwarding ist speziell für den SSH-Agent gemacht. Nehmen wir den Fall ich möchte mich auf einem SSH-Server hinter einer Firewall einloggen auf dem ich nicht direkt Zugriff habe. Ich habe jedoch auf einen anderen Rechner hinter der Firewall (oder auf die Firewall selbst) SSH-Zugriff. Von diesem anderen Rechner aus kann ich dann den eigentlich gewünschten Rechner erreichen (ich mache also sozusagen SSH über Bande). In einem solchen Fall ist es eventuell praktisch wenn für die Authentifizierung auch für die zweite SSH-Verbindung vom ersten entfernten Rechner zum Zielrechner mein lokaler SSH-Agent mitgenutzt werden kann. Genau dies leistet Agent-Forwarding.
Allerdings gilt auch hier die gleiche Warnung wie für das X11-Forwarding: Wer auch immer root-Rechte auf den Zwischenstationen hat, kommt ebenfalls an meine privaten Schlüssel auf dem lokalen Rechner heran, um sich damit auf anderen Rechnern einzuloggen. Agent-Forwarding sollte daher nur mit Bedacht eingesetzt werden (ich benutze es nur auf eigenen Systemen, auf denen ich der einzigste bin der root-Rechte hat).
ssh -A benutzer@server
Der Parameter -A aktiviert das Agent-Forwarding.
Der SSH-Server benutzt die Konfigurationsdatei /etc/ssh/sshd_config. In dieser Konfigurationsdatei stehen jeweils vorne ein Konfigurationsparameter und dahinter durch Leerschritt getrennt der zugehörige Wert. Ist eine Zeile mit einem "#" auskommentiert, wird für diesen Parameter der einkompilierte Defaultwert genutzt. Ich werde hier nicht alle Parameter besprechen, sondern mich auf die paar wichtigsten beschränken. Alle Parameter können in der Manpage zu sshd_config nachgelesen werden.
Port steht wie der Name schon sagt für den Port auf den der SSH-Server lauscht. Defaultwert ist 22. AddressFamily steht für das verwendete IP-Protokoll, also IPv4, IPv6 oder beide (any). Defaultwert ist any. ListenAddress ist die Netzwerkadresse auf der der Server lauscht, sofern der Server mehrere Netzwerkadressen, bzw. mehrere Netzwerkkarten hat. Als Default lauscht der Server auf allen konfigurierten Netzwerkinterfaces und Adressen. Protocol steht für das verwendete SSH-Protokoll, wobei es die SSH-Protokoll-Versionen 1 und 2 gibt. Die Protokollversion 1 ist veraltet und besitzt bekannte Sicherheitslücken. Sie sollte daher nicht mehr verwendet werden. Möchte man bevorzugt Protokoll 2 verwenden und als Fallback für alte Clients weiterhin Protokoll 1 anbieten kann man die Angabe "2,1" verwenden. HostKey gibt den Speicherort der SSH-Hostschlüssel an. Im allgemeinen sollte man diesen Wert nie verändern. ServerKeyBits gibt die Verschlüsselungsstärke in Bits an. SyslogFacility gibt die sogenannte Facility an in die Meldungen des SSH-Servers geloggt werden. LogLevel gibt die zugehörige Priorität ab der Meldungen geloggt werden an. Möglich sind hier alle Facilitys und Priorities die auch der Syslog-Dienst kennt (Default: Auth und Priority Info).
PermitRootLogin ist ein für die Sicherheit wichtige Option. PermitRootLogin bestimmt ob man sich über den SSH-Server direkt als root anmelden kann. Mögliche Werte sind yes, no und without-password. Mit without-password, kann man sich zwar direkt als root anmelden, aber nur über schlüsselbasierte Authentifizierung (also nicht mit dem root-Passwort). Am sichersten ist es direkten root-Zugriff mit no ganz auszuschalten und stattdessen sich als normaler User anzumelden und für den root-Zugriff su zu verwenden.
PasswordAuthentication bestimmt ob Passwort Authentifizierung erlaubt ist oder nicht (Default yes). Aber Vorsicht: Möchte man Passwort Authentifizierung zugunsten von schlüsselbasierter Authentifizierung ganz abschalten, muß man nicht nur PasswordAuthentication auf no setzen, sondern auf Linuxsystemen ebenso auch ChallengeResponseAuthentication. ChallengeResponseAuthentication Ist ein spezielles Authentifizierungsbackend mit dem Pluginartig verschiedene Authentifizierungsmechanismen, die auf dem jeweiligen Betriebssystem zur Verfügung stehen genutzt werden können. Unter Linux ist dies Passwortauthentifizierung über PAM. Unter Linux und anderen PAM nutzenden Systemen, ist die Passwortauthentifizierung darum erst abgeschaltet, wenn auch ChallengeResponseAuthentication abgeschaltet ist, weil über PAM ebenfalls die Passwörter abgefragt werden können. Unter OpenBSD z. B., wo es kein PAM gibt wird über ChallengeResponseAuthentication die Möglichkeit für S/Key basiertes Login konfiguriert (Bei S/Key handelt es sich um ein Einmalpasswortsystem).
AllowAgentForwarding bestimmt ob AgentForwarding erlaubt ist (Default yes). AllowTcpForwarding bestimmt ob Portforwarding möglich ist oder nicht (Default bei den meisten Distributionen yes). X11Forwarding bestimmt ob X11-Forwarding erlaubt ist oder nicht. Dieser Wert steht bei unterschiedlichen Distributionen per Default mal auf yes und mal auf no (meistens eher no).
ChrootDirectory ist eine recht interessante Direktive: Damit kann man SSH-Benutzer beim Login in ein Chroot-Verzeichnis einsperren. Dies zu verwirklichen benötigt jedoch noch einige zusätzliche Arbeitsschritte, die den Rahmen dieser Unterlagen sprengen würden.
Der ChrootDirectory Parameter ist erst bei neueren OpenSSH-Versionen zu finden (ab 4.9).Mit AllowGroups und AllowUsers läßt sich eingrenzen welche Benutzer sich auf dem System per SSH anmelden können. Dies kann auch ein guter Sicherheitsmechanismus sein, wenn es zwar viele angelegte Benutzer auf einem System gibt (z. B. Mailuser oder Sambauser), davon aber nur wenige (z. B. nur die Administratoren) sich auch per SSH am System anmelden können. AllowGroups erwartet eine Liste von Gruppen getrennt durch Leerzeichen. AllowUsers erwartet eine Liste von Benutzern, getrennt durch Leerzeichen. Möchte man umgekehrt nur einzelne Gruppen oder einzelne Benutzer aussperren gibt es auch DenyUsers und DenyGroups.
Darüber hinaus gibt es auch noch Match-Blöcke. Mit einem Match Block kann man Ausnahmen für bestimmte Konfigurationsoptionen definieren, die nur für bestimmte Gruppen, Benutzer oder Quelladressen gelten. Innerhalb eines Match-Blockes kann man allerdings nicht alle Konfigurationsoptionen verwenden. Einige erlaubte Konfigurationsoptionen sind z. B. AllowAgentForwarding, AllowTCPForwarding, ChrootDirectory, ForceCommand, PasswordAuthentication, PermitRootLogin und X11Forwarding. Eine Besonderheit stellt dabei ForceCommand dar, welches eigentlich nur in einem Match-Block Sinn macht. Mit ForceCommand kann man bestimmen das nur ein bestimmtes angegebenes Kommando ausgeführt werden darf, egal welches Kommando der Client sonst noch ausführen möchte. Loggt sich solch ein Client per SSH ein, bekommt dieser keine Shell, sondern nur das Kommando wird ausgeführt und die Verbindung danach wieder beendet.
Hier ein praxisnahes Beispiel für Match-Blöcke in der Konfigurationsdatei:
Match User backup
ForceCommand backupscript
Match User herbert
X11Forwarding yes
AllowTCPForwarding no
PasswordAuthentication yes
Match Address 192.168.1.34
PermitRootLogin without-password
In diesem Beispiel gibt es 3 Match-Blöcke. Die zu einem Match-Block gehörenden Optionen stehen jeweils eingerückt darunter. Im ersten Match-Block wird bestimmt, daß der User backup nur das Kommando backupscript ausführen darf. Eine interaktive Shell würde dieser User also nicht bekommen. Im zweiten Match-Block wird dem User herbert X11Forwarding erlaubt (Falls X11Forwarding global verboten ist), aber Port-Forwarding wird ihm verboten (falls es global erlaubt wäre). Außerdem darf sich der user herbert auch Passwortbasiert anmelden (falls die Passwortauthentifizierung global deaktiviert ist). Der dritte Match-Block bezieht sich nicht auf einen User, sondern auf eine IP-Adresse von der die Verbindung stammt. Hier wird bestimmt das Verbindungen von dem Host mit der IP 192.168.1.34 sich schlüsselbasiert auch als root direkt anmelden können, auch wenn global root-Login deaktiviert ist. PermitRootLogin macht in Match-Blöcken nur Sinn wenn diese Match-Blöcke sich auf Adressen beziehen.
Es gibt neben der Server-Konfigurationsdatei auch eine Client-Konfigurationsdatei: /etc/ssh/ssh_config. Zusätzlich zu dieser Systemweit gültigen Client Konfigurationsdatei kann auch jeder User seine eigene Konfiguration in die Datei ~/.ssh/config schreiben. In beiden Dateien sind die gleichen Konfigurationsoptionen möglich.
Ebenso wie es in der Server-Konfiguration Match-Blöcke gibt, gibt es in der Clientkonfiguration auch die Möglichkeit einzelne Optionen pro Host, mit dem man sich verbinden will, festzulegen. Viele Optionen sind sogar nur dann nützlich, wenn man diese pro Host festlegt.
Eine Option die allerdings global festgelegt werden muß ist HashKnownHosts (in älteren OpenSSH-Versionen noch nicht vorhanden). Diese Option schreibt, wenn sie aktiviert ist, Hostnamen in der Datei ~/.ssh/known_hosts nicht mehr im Klartext rein, sondern als Hash. Dies dient dazu Hostnamen bei Verlust der Datei geheim zu halten. Benutzt man diese Option kann man Hostnamen in der known_hosts nur noch mit Hilfe von ssh-keygen wiederfinden:
ssh-keygen -F hostname -f ~/.ssh/known_hosts
Dieser Befehl sucht den Hostnamen hostname in der Datei ~/.ssh/known_hosts.
Ich persönlich nutze diese Funktion nicht, da Hostnamen im allgemeinen nichts allzu geheimes sind und der Sicherheitsgewinn nicht allzu groß ist, wohingegen es recht umständlich ist Hostnamen erst mit ssh-keygen suchen zu müssen. Der Default ist auch no, allerdings ist bei Debian neuerdings diese Funktion an.
Ein Beispiel für eine Clientkonfigurationsdatei:
HashKnownHosts no
Host meinserver
Hostname meinserver.domain
user heinrich
Compression yes
Host meindesktop
Hostname meindesktop.domain
user hmueller
ForwardX11 yes
ForwardX11Trusted yes
ForwardAgent yes
Host firewall
Hostname gateway.firma.com
user hmueller
Port 222
LocalForward 8000 webserver:80
In dieser Beispiel-Client-SSH Konfiguration wird zunächst global HashKnownHosts ausgeschaltet. Danach gibt es 3 Blöcke für 3 verschiedene Server. Mit Host wird ein Block eingeleitet und ein Name für den Host vergeben. Dieser kann durchaus vom echten Hostnamen abweichen und ist der Name den man später beim ssh-Befehl für diesen Host angibt. Man kann hier also auch griffige Abkürzungen für oft benutzte Rechner verwenden. Die zu einem einzelnen Server gehörenden Teile sind jeweils eingerückt. Mit Hostname wird der eigentliche Hostname, so wie er im DNS steht angegeben. Mit user kann man einen Usernamen angeben. Sollte dann der Benutzername auf dem entfernten Server von dem lokalen abweichen, muß man ihn trotzdem nicht jedesmal auf der Kommandozeile angeben. Übrigens überschreiben immer auf der Kommandozeile gemachte Angaben, die Angaben in der Konfigurationsdatei. Mit Compression wird eine Kompression der Datenpakete bei der Übertragung eingeschaltet. Dies kostet mehr CPU-Zeit, benötigt auf der Leitung aber auch weniger Bandbreite. Diese Option empfiehlt sich bei langsamen Verbindungen, wie etwa mit ISDN oder GPRS.
Beim zweiten Hostspezifischen Beispiel, wird der Host meindesktop.domain über den Namen meindesktop angesprochen und als Benutzername hmueller verwendet. Trusted X11 Forwarding wird jedesmal eingeschaltet (muß also nicht mehr auf der Kommandozeile angegeben werden), ebenso Agent-Forwarding. Für den Host gateway.firma.com wird der Kurzname firewall gewählt. Der Benutzername ist auch wieder hmueller. Außerdem wird ein anderer Port benutzt: 222, statt den Default von 22. Zusätzlich wird bei jedem Verbindungsaufbau auch ein Portforwarding aktiviert vom lokalen Port 8000 auf den Port 80 des Hosts webserver. Würde man diese Konfiguration so auf der Kommandozeile angeben, sähe die entsprechende Zeile so aus:
ssh -p 222 -L 8000:webserver:80 hmueller@gateway.firma.com
Statt dessen muß mit obiger Konfigurationsdatei nur noch folgendes angegeben werden:
ssh firewall
Es existiert auch eine Möglichkeit Verbindungen mit SSH über einen Proxy aufzubauen. Sollte man hinter einer Firewall sitzen, welche SSH Verbindungen nicht durchläßt, jedoch die Möglichkeit bietet über einen Proxy auch SSL-Verbindungen an Port 443 (per HTTP-CONNECT Methode) aufzubauen, kann mit Hilfe eines zusätzlichen Programms eine SSH Verbindung durch den SSL-Proxy aufgebaut werden. Hierzu existiert in der Client Konfiguration die Direktive ProxyCommand. Diese Direktive erwartet ein Kommando welches beim Verbindungsaufbau ausgeführt wird. In das Kommando können als Argumente auch die Variablen %h für den Zielhostnamen und %p für den Zielport eingefügt werden. Als Kommando eignet sich für diesen Zweck zum Beispiel nc (netcat) welches beliebige Netzwerkverbindungen auch über SSL-Proxys aufbauen kann. Damit der Verbindungsaufbau auf den Zielserver über den Proxy klappt muß der Zielserver so konfiguriert sein, daß er auch auf Port 443 lauscht (Direktive Port in der sshd_config). Die entsprechende Konfiguration eines Hosts in der Clientkonfiguration könnte dann zum Beispiel so aussehen:
Host fernerhost
Hostname fernerhost.example.com
User meinuser
Port 443
ProxyCommand /bin/nc -X connect -x 192.168.5.79:8080 %h %p
In diesem Beispiel wird die Verbindung über den Proxy mit der IP 192.168.5.79 und an die Portnummer 8080 aufgebaut (Option -x von nc). Mit der Option -X von nc wird bestimmt welches Protokoll der Proxy verwendet. Derzeit unterstützt nc die Protokolle Socks 4, Socks 5 und die HTTP CONNECT Methode. Als letztes werden über die entsprechenden Variablen Zielhostname und Zielhostport übergeben.
Neben den hier vorgestellten Optionen gibt es noch einige weitere, welche in den Manpages zu ssh, ssh_config und sshd_config zu finden sind.
Sven Riedel: SSH kurz & gut, O'Reilly, 2006.