SSH - Secure SHell

Einleitung

Die Secure SHell ist sowohl Protokoll als auch Programm und ersetzt gleich eine ganze Gruppe von Anwendungen:

  • rsh, rlogin, telnet
  • rexec
  • rcp, ftp

Im Gegensatz zu den oben genannten Protokollen findet die Übertragung komplett verschlüsselt statt, so dass die übermittelten Benutzernamen und Passwörter nicht ausgespäht werden können. Außerdem ist es möglich, fast jedes andere unsichere Protokoll durch einen sogenannten SSH-Tunnel zu schicken und dieses damit abzusichern.

Im Folgenden wird angenommen, dass der SSH-Daemon auf einem Rechner läuft, der einerseits mit dem Internet und andererseits mit einem lokalen Netzwerk verbunden ist. Das lokale Netzwerk hat die Netzadresse 192.168.1.0 und die Subnetzmaske 255.255.255.0. Die interne IP-Adresse des Rechners ist 192.168.1.1.

« zurück (Gesammelte Anleitungen)

Inhalt

Sichere Konfiguration

Wirklich sicher ist nichts. Aber man kann die Risiken minimieren, bzw. es den Angreifern nicht ganz so einfach machen. Grundsätzlich stellt sich erstmal die Frage:

Von wo aus melde ich mich an meinem System an? Von Außerhalb oder nur vom Inneren meines eigenen Netzwerks?

Für den letzteren Fall macht es erst einmal Sinn, den SSH-Daemon nur an die interne IP-Adresse zu binden, damit er von Außen erst gar nicht erreicht werden kann. Hierfür muss man in der Konfigurationsdatei /etc/ssh/sshd_config folgende Zeile einbinden oder ändern:

ListenAddress 192.168.1.1

In diesem Fall lauscht der SSH-Daemon nun auf die IP-Adresse 192.168.1.1, die nur intern erreichbar ist. Anfragen aus anderen Netzen, wie z. B. dem Internet, werden nicht angenommen.

SSH gibt es in zwei Protokollversionen. Bei der in die Tage gekommenen Version 1 sind inzwischen einige konzeptionelle Sicherheitslücken bekannt und somit sollte diese Version nicht mehr benutzt werden. Das kann mit der folgenden Zeile erreicht werden:

Protocol 2

Man kann jetzt noch die Benutzer beschränken, die sich überhaupt via SSH auf diesem Rechner einloggen dürfen. Den direkten root-Zugang kann man separat verbieten. Der Gedanke ist, dass man für die Kontrolle zwei Passwörter, nämlich erst das eines normalen Nutzers und anschließend das des Systemverwalters root benötigt.

Was dem Gedanken entgegen steht ist einerseits ein eventueller Fehler im sshd-Programm, der eventuell aus der Ferne ausnutzbar ist und einen direkten root-Zugang ermöglicht. Auf der anderen Seite wären auch noch eventuelle Fehler in auf dem Rechner mit root-Rechten laufenden Server-Anwendungen, mit denen man dann ohne das Passwort zu root-Rechten kommen kann.

Aus der oben genannten Poblematik wird ersichtlich, dass für jeden Benutzer des Systems ein gutes Passwort vergeben werden sollte, denn wie heißt es so treffend: "Die Kette bricht am schwächsten Glied".

Wie auch immer, so kann man den direkten root-Zugang sperren:

PermitRootLogin no

Leere Passwörter sollte man sowieso nicht haben, hier kann man sie aber noch einmal explizit sperren. Außerdem dürfen sich nur diejenigen Benutzer anmelden, die Mitglied der Gruppe ssh sind:

PermitEmptyPasswords no
AllowGroups ssh

Der SSH-Daemon verfügt noch über weitere Möglichkeiten, Berechtigungen und Features wie z. B. das unten genannte Port Forwarding per Default zu verbieten. Die dafür nötigen Optionen sind in der Manpage sshd_config(5) beschrieben.

« nach oben

Benutzereinstellungen ($HOME/.ssh/config)

Wozu braucht man diese Einstellungen überhaupt?

Ganz einfach: Der Bequemlichkeit halber, um dem SSH-Programm nicht immer alle Optionen mitgeben zu müssen oder Alternativ n Aliase für jeden speziellen Rechner in der Shell zu erstellen. Die Syntax ist einfach:

Host erster_server.example.com
  [... Optionen für den ersten Server ...]

Host zweiter_server.example.com
  [... Optionen für den zweiten Server ...]

[...]

Host *
  [... Optionen für die restlichen Server ...]

Für das bessere Verständnis ein paar Beipiele. Will man zum Beispiel X11Forwarding für sein schnelles internes Netzwerk standardmäßig einschalten, für alle externen Rechner jedoch nicht, könnte das z. B. so aussehen:

Host 192.168.1.*
  ForwardX11 yes

Host *
  ForwardX11 no

Eventuell ist ein SSH-Server auch mal nicht an den Standard-Port 22 gebunden, sondern einen ganz anderen (hier 50022), dann kann man das für den Rechner speziell angeben:

Host 192.168.1.23
  ForwardX11 yes
  Port 50022

Die Optionen für die einzelnen Hosts sind beliebig ausbaubar. Alle möglichen Optionen für die Konfiguration befinden sich in der Manpage ssh_config(5).

« nach oben

Authentisierung mit PublicKey-Verfahren und SSH-Agent

Wer mit SSH viel arbeiten muss und auch das Kopieren mit SCP nutzt, wird schnell den vielen Passworteingaben überdrüssig werden. Die komfortablere Variante ist die Benutzung einer Authentisierung via PublicKey-Verfahren.

Erzeugen eines Schlüsselpaares

Zuallererst muss man ein Schlüsselpaar generieren, das man im Verzeichnis $HOME/.ssh ablegt.

$ ssh-keygen -b 2048 -t dsa -f $HOME/.ssh/id_dsa
Generating public/private dsa key pair.
Enter passphrase (empty for no passphrase):

An dieser Stelle wird man nach dem Passwort für diese Identität gefragt, dass man später für die Authetisierung einmal pro Sitzung eingeben muss. Es gelten die üblichen Passwortrichtlinien (also z. B.: kein Wort aus dem Lexikon, mindestens 8 Zeichen, ein paar Sonderzeichen, etc.). Es ist sogar erlaubt, kein Passwort zu vergeben, was ich aus Sicherheitsgründen aber nicht empfehle, denn gerät der Schlüssel einmal in die falschen Hände, sind sämtliche Server, auf denen der Schlüssel als vertraut gilt, für diese Person ohne Passwort zugänglich.

Exportieren des öffentlichen Schlüssels

Der soeben generierte Schlüssel muss auf allen Rechnern bekannt gemacht werden. Hier liegt ein kleiner Haken des Systems: Im Falle von sehr vielen Rechnern ist das Aktualisieren der Schlüssel für alle Rechner zeitaufwändig, wenn man es von Hand machen muss. Als eine mögliche Automation könnte man sich ein Skript schreiben, dass die Arbeit automatisch erledigt, z. B. unter Zuhilfenahme des Programms expect.

Das Exportieren des öffentlichen Schlüssels an einen Rechner erfolgt über das folgende Kommando:

$ ssh-copy-id -i $HOME/.ssh/id_dsa.pub user@rechnername

Hierbei sind "user" der Loginname und "rechnername" der Hostname des Rechners, unter dem der Schlüssel bekannt gemacht werden soll. Die Schlüssel sind also auch an einen bestimmten Benutzer gebunden.

Bekanntmachen des Schlüssels beim SSH-Agenten

Bisher schien das Ganze keinen wirklichen Vorteil zu bringen, sondern eher einen Mehraufwand, da man ja immer noch das Passwort eingeben muss. Für den Komfort bietet sich der SSH-Agent an, bei dem man lediglich einmal pro Sitzung das Passwort für seine Identität (also den Schlüssel) eingeben muss. Unter debian wird dieser für jede X-Session automatisch gestartet. Falls der SSH-Agent nicht gestartet sein sollte, kann dies mit

$ eval `ssh-agent`

nachgeholt werden. Die Identität kann dann mit dem Kommando

$ ssh-add

und anschließender Eingabe des Schlüssel-Passwortes hinzugefügt werden.

Ab diesem Zeitpunkt wird für jede weitere SSH-Sitzung oder SCP-Kommandos der SSH-Agent zu Rate gezogen und man wird nicht weiter mit Passwortabfragen "belästigt". Wenn einem auch das nicht reicht, kann man sich auch via SSH und PAM am System anmelden.

Mit PAM und SSH direkt am System anmelden

Für die Anmeldug via SSH ist das Paket libpam-ssh notwendig. Man kann es unter debian mit folgendem Kommando installieren:

# apt-get install libpam-ssh

Anschließend muss man die PAM-Datei für den verwendeten Login-Manager anpassen. Bei mir ist das die Datei für KDM, den KDE Display Manager:

# /etc/pam.d/kdm - specify the PAM behaviour of kdm
#
auth       required     pam_nologin.so
auth       required     pam_env.so
auth       required     pam_nologin.so
auth       required     pam_env.so readenv=1
auth       required     pam_env.so readenv=1 envfile=/etc/default/locale
@include common-auth
@include pam-ssh-auth
# entspricht: auth sufficient pam_ssh.so try_first_pass keyfiles=id_dsa,id_rsa,identity,id_dsa1,id_dsa2,id_dsa3
@include common-account
session    required     pam_limits.so
@include common-session
@include pam-ssh-session
# entspricht: session optional pam_ssh.so
@include common-password

Nach einem Restart des KDE Session Managers mit

# /etc/init.d/kdm restart

werden die Änderungen übernommen. Vor dem Neustart die aktuelle X-Sitzung beenden, da diese von KDM abhängt und sonst beim Neustart unsanft beendet würde und während dieser Sitzung geänderte Dateien dann nicht gespeichert würden.

Wenn alles geklappt hat, sollte nun nach einem Aufruf von ssh-add -l in einem Konsolenfenster die ID angezeigt werden:

$ ssh-add -l
1024 12:34:56:78:9a:bc:de:f0:12:34:56:78:9a:bc:de:f0 /home/username/.ssh/id_dsa (DSA)

Die debian-spezifische Dokumentation dazu befindet sich wie immer unter /usr/share/doc/libpam-ssh/README.Debian.

« nach oben

SSH Tunneling und Port Forwarding

Arten des Port Forwarding

  • Local Port Forwarding: Weiterleiten eines angegebenen Ports auf dem lokalen Rechner (Client), der an einen entfernten Rechner durchgereicht werden soll.
    Diese Artder Weiterleitung wird benutzt, wenn man auf einen Dienst auf dem entfernten Rechner zugreifen will, das der am meisten gewünschten Nutzung der Portweiterleitung entspricht.
  • Remote Port Forwarding: Weiterleitung eines angegebenen Ports vom entfernten Rechner auf einen angegebenen Rechner und Port im lokalen Netzwerk.
    Diese Art der Portweiterleitung wird eher selten benötigt, z. B. wenn der Rechner im entfernten Netz aufgrund des Firewallkonzepts keine Verbindung zum Internet hat, man aber das Betriebssystem über das Web aktualisieren oder Pakete nachinstallieren möchte. In dem Beispiel wird genau dieser Fall dargestellt, dass ein Rechner im entfernten Netz auf einen lokalen Squid-Proxy zugreift.

Die Pfeile in den Bildern der Beispiele zeigen immer in Richtung der Serveranwendung, auf die zugegriffen werden soll.

Hinweis: Ports unter 1024 können nur von dem Benutzer root zum Lauschen (Listen) geöffnet werden. Falls ein Tunnel fehlschlagen sollte, dies bitte im Hinterkopf behalten!

Local Port Forwarding

Secure SHell ist wie bereits erwähnt verschlüsselt und zählt somit zu den gesicherten Übertragungsarten in einem Netzwerk. Es gibt aber eine Vielzahl von Diensten, die mit Klartextübertragungen arbeiten, so dass z. B. Zugangsdaten leicht ausgespäht werden können. Beispiele hierfür sind FTP, dass für Datenübertragungen verwendet wird oder POP3, mit dem man seine Mails von seinem Provider abholt.

Falls man auf dem betreffenden Rechner einen SSH-Zugang hat, kann man diese Dienste über einen sogenannten SSH-Tunnel absichern. Das Prinzip ist einfach: Auf beiden Seiten werden quasi Sende- und Empfangsstation eingerichtet, die die Daten vor der Übertragung verschlüsseln und beim Empfang auf der anderen Seite wieder entschlüsseln und dann weiterreichen. In der Regel möchte man einen Serverdienst von einem anderen Rechner auf seinen Arbeitsrechner tunneln. Das ist dann das sogenannte Local Port Forwarding. Hier ein Beispiel, wie man POP3 (Port 110) von einem entfernten Server zu der lokalen Workstation tunnelt:

$ ssh -L 50500:entfernter_server:110 user@entfernter_server

Hier sieht man schon einen Nachteil dieses Verfahrens: Die Ports unter 1024 (hier: 110) können nur von Superuser root getunnelt werden. Gemäß dem Fall, man hätte diese Rechte, weil es z. B. der eigene Server ist, kann man seine Mails nun bei sich selbst abholen, genauer bei localhost auf Port 50500.

WWW-Proxy Tunnel - Surfen wie im lokalen Intranet

Eine sinnvollere Anwendung, die auch ein wenig mehr der Praxis entspricht ist die Möglichkeit, den Proxy-Server seiner Universität oder Fachhochschule nach Hause zu tunneln, damit man sich mit seinem Browser wie im Hochschulnetz bewegen kann. Hier der schematische Aufbau der Verbindung:

Local Port Forwarding auf einen entfernten Rechner über Shell-Server

Man meldet sich am Shell-Server an und baut von dort eine weitere Verbindung zum Proxyserver auf, für den man keinen Shell-Zugang benötigt, was in der Regel auch nicht der Fall ist. Das Kommando für die oben dargestellte Verbindung lautet:

$ ssh -L 3128:proxyserver:3128 user@ssh-server

Jetzt braucht man nur noch die Proxy-Einstellungen des Webbrowsers auf localhost und Port 3128 zu stellen und kann surfen, als würde man im Rechnerpool der Hochschule sitzen. :-)

« nach oben

Remote Port Forwarding

Jetzt möchte man gerne einen lokalen Dienst für einen Rechner im entfernten Netzwerk bereit stellen. Das hier gezeigte Beispiel tunnelt einen WWW-Proxy (z. B. Squid) in ein entferntes Netz, um Softwarepakete aus dem Internet nachzuinstallieren.

Hinweis: Bei dieser Vorgehensweise handelt es sich um ein gezieltes Umgehen eines bestehenden Firewall-Konzepts, was unter Umständen nicht erlaubt ist und personaltechnische Folgen haben könnte. Die Erlaubnis ist also vorher beim Verantwortlichen Administrator einzuholen.

Voraussetzung für das Remote Port Forwarding ist ein Shellzugang auf dem entfernten Rechner, da auf diesem ein Port geöffnet werden soll, der an den WWW-Proxy des lokalen Systems durchgereicht wird. Hier eine Übersicht des zweistufigen Tunnels:

Remote Port Forwarding von einem entfernten Rechner über Shell-Server

Zuerst meldet man sich auf dem SSH-Server an und stellt die Verbinung zwischen SSH-Server und dem lokal laufenden WWW-Proxy her:

user1@local-pc$ ssh -R 5000:ssh-server:3128 user2@ssh-server

Mit dem ersten Tunnel ist es nun möglich, den lokalen WWW-Proxy über die URL http://localhost:5000/ vom SSH-Server aus anzusprechen. Da das aber nicht der Endpunkt sein soll, benötigen wir noch den zweiten Tunnel:

user2@ssh-server$ ssh -R 8080:remote-pc:5000 user3@remote-pc

Jetzt sind wir am remote-pc angemeldet und können die Umgebungsvariable HTTP_PROXY bzw. FTP_PROXY entsprechend auf http://localhost:8080/ setzen:

user3@remote-pc$ HTTP_PROXY="http://localhost:8080/"
user3@remote-pc$ export HTTP_PROXY

Eventuell kann oder muss man den Proxy für die Anwendung auch über die Konfigurationsdatei des Programms separat setzen.

Wichtig bei diesem zweistufigen Tunnel ist, dass die rot dargestellten Ports übereinstimmen, da sie quasi das Verbindungsstück zwischen den beiden Portweiterleitungen darstellen. Die verschiedenen Benutzer-IDs user1, user2 und user3 können unter Umständen teilweise oder auch komplett übereinstimmen.

Eventuell würde auch schon ein einfacher Tunnel reichen:

user1@local-pc$ ssh -R 8080:ssh-server:3128 user2@ssh-server

Wenn man von dem entfernten Rechner auf Port 8080 des SSH-Servers zugreifen darf, kann man die Umgebungsvariablen auf dem entfernten Rechner wie folgt setzen:

user3@remote-pc$ HTTP_PROXY="http://comserver:8080/"
user3@remote-pc$ export HTTP_PROXY

Den Shell-Zugang benötigt man aber nach wie vor auf beiden Rechnern. :-)

« nach oben

« zurück (Gesammelte Anleitungen)weiter (SSH Teil 2) »