Die Secure Shell ist der Goldstandard für sicheren Shell-Zugriff auf entfernte Rechner.
Selbst in einem lokalen Netzwerk lohnt es sich, das Übertragen der Daten auf einem verschlüsselten Kanal zu erledigen. Als Bordmittel drängt sich die Secure Shell dabei als naheliegende Lösung geradezu auf.
Mit SFTP und dem FUSE-Dateisystem SSHFS gibt es dafür zwei Ansätze, die einen unterschiedlichen Grad an Komfort bieten. SFTP, eine verschlüsselte Variante des bekannten, aber mittlerweile in die Jahre gekommenen Protokolls FTP, erlaubt es, den Zugriff auf Daten oder sogar auf einen Rechner erheblich einzuschränken. So setzen Sie einen kleinen Server auf, dessen Infrastruktur nicht für alle Teilnehmer im LAN bereitsteht.
Umgebung abschotten
Es bietet sich an, SFTP-Benutzer in eine Art Chroot-Umgebung einzusperren, die keinen Zugriff auf die Shell erlaubt. Auf diese Weise kann eine nicht ausgelastete Maschine beispielsweise nebenbei noch NAS-Aufgaben übernehmen. Aber selbst für einen Daten-Pool, den Sie vom Internet aus bedienen, ist dies interessant.
Wenn Sie eine solche Lösung implementieren, lohnt es sich, einige Gedanken in die Sicherheit des SFTP-Servers zu investieren. So erhöhen Sie diese, wenn Sie root allenfalls den Zugriff aus dem lokalen Netz oder besser ausschließlich via localhost erlauben.
Diese und andere Maßnahmen legen Sie in der Konfiguration des SSH-Daemons unter /etc/ssh/sshd_config fest. Parallel lohnt es sich, eine zusätzliche Gruppe (im Beispiel nennen wir sie speichergruppe) anzulegen. Um den SFTP-Server zu aktivieren, kommentieren Sie als Erstes in der Konfigurationsdatei die folgende Zeile aus:
Subsystem sftp /usr/lib/openssh/sftp-server
Anschließend fügen Sie einen neuen Eintrag am Ende der Datei hinzu (Listing 1). Dabei geben Sie das abzuschottende Verzeichnis an, die Benutzergruppe sowie weitere Anweisungen. Eine davon verhindert ein TCP-Forwarding, die andere beschränkt die Benutzer der angegebenen Gruppe auf das Ausführen von sftp. Ein Login in eine Shell gelingt so nicht.
Listing 1
Subsystem sftp internal-sftp Match Group speichergruppe ChrootDirectory /home/speicher ForceCommand internal-sftp AllowTcpForwarding no
Anschließend starten Sie den SSH-Server neu, was Sie je nach Distribution über einen der beiden Befehle aus Listing 2 erledigen. Legen Sie die Speichergruppe an (Listing 3, Zeile 1) sowie das Verzeichnis, das Sie in der Variablen ChrootDirectory in der Konfiguration des SSH-Servers (Listing 1, Zeile 4) angegeben haben (Listing 3, Zeile 2).
Listing 2
### SysVinit $ /etc/init.d/ssh restart ### Systemd $ systemctl restart ssh.service
Listing 3
$ sudo addgroup speichergruppe $ sudo mkdir -p /home/speicher $ sudo usermod -G speichergruppe User $ sudo usermod -s /bin/false User
Damit haben Sie die Vorarbeiten abgeschlossen. Nun legen Sie bei Bedarf noch den oder die Benutzer an. Möchten Sie diese Benutzer aus allen anderen Gruppen entfernen, erledigen Sie das mit dem Befehl aus Listing 3. Außerdem lohnt es sich, in diesem Fall die Login-Shell zu ändern und das Home-Verzeichnis entsprechend zu modifizieren.
Dieses manuelle Anlegen eines solchen Benutzers besteht aus einigen Einzelschritten. Mittels Skript (Listing 4) erledigen Sie diese aber fast automatisch.
Listing 4
#! /bin/sh echo "Neuen Speicherbenutzer anlegen" # Benutzernamen erfragen echo -n "Benutzername: "; read ben # Aktion wirklich durchführen? echo -n "$ben anlegen? (j) "; read we if [ "$we" != "j" ]; then exit fi # Neues Home-Verzeichnis fuer Benutzer anlegen, # verhindert das Kopieren der Skel-Dateien. mkdir /home/speicher/$ben # Benutzer anlegen useradd -b /home/speicher -s /bin/false -G speichergruppe $ben # Verzeichnis anlegen und Rechte erteilen chown $ben:speichergruppe /home/speicher/$ben/ chmod 700 /home/speicher/$ben/ # Kennwort manuell vergeben passwd $ben
Mit dem Skript legen Sie ein Verzeichnis für den Benutzer unterhalb des Eintrags aus /etc/ssh/sshd_config an, im Beispiel also /home/speicher/User. Mittels chmod 700 schotten Sie die SFTP-Benutzer gegeneinander ab, niemand darf also in das Verzeichnis eines anderen SFTP-Benutzers absteigen.
Des Weiteren legen Sie bei Bedarf ein neues Konto unter Angabe der Gruppe speichergruppe und der Shell /bin/false an. Das Basisverzeichnis (hier: /home/speicher/) geben Sie bei useradd mit der Option -b an. Am Ende erhält der neue Account noch ein Passwort. Abbildung 1 zeigt das Anlegen eines Benutzers und ermöglicht einen Blick auf die entstandene Verzeichnisstruktur.
Für die Direktive ChrootDirectory sieht die Software eigentlich den Einsatz von Tokens wie %u für den Benutzernamen oder %h für das jeweilige Home-Verzeichnis vor. Das würde die Pfade dynamisch anpassen. Im Test funktionierte das aber in mehreren Konstellationen nicht.
Möglicherweise wollen Sie ein Benutzerkonten zu einem späteren Zeitpunkt wieder loswerden. Dazu löschen Sie den User aus der Benutzerverwaltung und entfernen das zugehörige Verzeichnis von Hand. Ein kleines Shell-Skript verdeutlicht hier wieder die Abläufe (Listing 5). Bei solchen Aktionen empfiehlt es sich, die entscheidenden Schritte mit einer Sicherheitsabfrage zu versehen. Abbildung 2 zeigt, wie der Administrator den Benutzer speicher2 wieder entfernt.
Listing 5
#! /bin/sh echo "Löschen von Speicherbenutzern" # Benutzernamen erfragen echo -n "Benutzername: ";read ben # Aktion wirklich durchführen? echo -n "$ben löschen? (j) ";read we if [ "$we" != "j" ]; then exit fi # Benutzer löschen userdel $ben # Verzeichnis löschen? echo -n "Benutzerverzeichnis löschen? (j) "; read wn # Aktion wirklich durchführen? if [ "$wn" != "j" ]; then exit fi rm -r /home/speicher/$ben

Abbildung 2: Benötigen Sie einen Account nicht mehr, empfiehlt es sich, diesen zu löschen, um keine unnötigen Einfallstore auf dem Server zu haben.
Arbeiten mit SFTP
Der SFTP-Client verfügt über verschiedene Kommandos für den interaktiven Modus. Die Optionen decken sich mehr oder weniger mit denen von Ssh und Scp. In der Tabelle “SFTP-Kommandos” finden Sie die Anweisungen, getrennt nach der lokalen und entfernten Seite.
|
Aufgabe |
lokal |
entfernt |
|---|---|---|
|
Verzeichnis wechseln |
|
|
|
Verzeichnisinhalt auflisten |
|
|
|
Verzeichnis anlegen |
|
|
|
Aktuelles Verzeichnis |
|
|
|
Daten senden |
– |
|
|
Verzeichnis übertragen |
– |
|
|
Abgebrochenen Transfer fortsetzen |
– |
|
|
Dateien herunterladen |
– |
|
|
Verzeichnis herunterladen |
– |
|
|
Abgebrochenen Download fortsetzen |
– |
|
|
Objekte umbenennen |
– |
|
|
Dateien löschen |
– |
|
|
Verzeichnis löschen |
– |
|
|
Lokale Shell erreichen |
– |
|
|
Hilfe aufrufen |
– |
|
|
Client beenden |
– |
|
Mit den Befehlen ermöglichen Sie eine recht weitgehende Kontrolle über alle wichtigen Dateioperationen. Anhand des Beispiels in Abbildung 3 sehen Sie, wie Sie den Inhalt eines lokalen Verzeichnisses auflisten, eine Datei senden, den Inhalt eines entfernten Verzeichnisses auflisten (Option -l), eine Datei herunterladen und den Vorgang kontrollieren, indem Sie nochmals den Inhalt des lokalen Verzeichnisses auflisten.

Abbildung 3: Das Übertragen von Dateien via SFTP gelingt trotz Einsatz auf der Kommandozeile nach ein wenig Einarbeiten häufig relativ problemlos.
SSHFS im Einsatz
Es gibt einige Programme, die das SFTP-Protokoll unterstützen. Der Einsatz des Userspace-Dateisystems SSHFS macht den Zugriff jedoch etwas transparenter. Einige Dateimanager beherrschen das direkte Einbinden solcher Verzeichnisse.
Als Grundlage dient dafür der Befehl sshfs, der wiederum eine komplett eingerichtete FUSE-Umgebung erwartet. Sie ermöglicht es normalen Benutzern, entfernte Verzeichnisse in den Baum einzuhängen. Listing 6 zeigt die entsprechende Syntax.
Listing 6
$ sshfs User@Rechner:/Pfad /Verzeichnis
Mit dem eingehängten, auf einem entfernten Rechner liegenden Verzeichnis arbeiten Sie wie mit einem lokalen Ordner. Abbildung 4 zeigt Ihnen das Einhängen, das Verzeichnis selbst und das Aushängen. Für Letzteres verwenden Sie folgende Syntax:
fusermount -u /Verzeichnis
Beim Aushängen darf keine Applikation mehr auf das fragliche Verzeichnis zugreifen. Gegebenenfalls ermitteln Sie über lsof Verzeichnis, welcher Prozess das Aushängen blockiert (Abbildung 5).

Abbildung 4: Dank SSHFS greifen Sie auf entfernte Verzeichnisse transparent zu, als lägen diese auf dem lokalen Host.

Abbildung 5: Mit dem Befehl lsof ermitteln Sie, ob eine Applikation auf ein via SSHFS eingehängtes Verzeichnis zugreift. Ist das der Fall, lässt es sich nicht aushängen.
SSH-Tunnel
Ansätze wie SFTP oder SSHFS sorgen dafür, dass der Datentransfer verschlüsselt über das Netzwerk läuft. Es gibt aber Programme, die keine eigenen Funktionen zum Verschlüsseln mitbringen. Diesen verhelfen Sie mit einem SSH-Tunnel zu einer sicheren Verbindung.
Als normaler Benutzer dürfen Sie zu diesem Zweck nur Port-Nummern über 1024 verwenden. Einen einfachen Tunnel bauen Sie auf, indem Sie in einem Terminal einen Befehl absetzen, der der Syntax aus der ersten Zeile von Listing 7 folgt.
Listing 7
$ ssh -LLokalerPort:Rechner:Port User@Rechner $ ssh -N -R LokalerPort:localhost:Port User@Rechner
Abbildung 6 zeigt das Konstrukt im Einsatz: Auf dem Zielsystem arbeitet ein Webserver, auf den ein Benutzer verschlüsselt zugreift. Dazu baut er zunächst den Tunnel auf (großes Terminal). Anschließend startet er den Shell-Webbrowser Elinks mit der URL http://localhost:8080 in einem anderen Terminal.

Abbildung 6: Mit einem SSH-Tunnel bauen Sie für eine Applikation eine verschlüsselte Verbindung zu einem anderen Rechner für einen HTTP-Zugriff auf.
In die umgekehrte Richtung arbeitet das Kommando mit der Option -R (“Reverse Tunnel”). Die zugehörige Syntax zeigt die zweite Zeile von Listing 7. Hier bauen Sie ebenfalls zunächst den Tunnel auf, bevor die Software darauf zugreift. Der Browser Elinks arbeitet in derselben Weise wie beim normalen Tunnel (Abbildung 7).
Kontrolle aus der Ferne
Listing 8 zeigt einen Anwendungsfall aus der Praxis. Ein Benutzer mit nur geringen Kenntnissen kann damit einen Rechner überwachen.
Listing 8
#!/bin/bash
# menu.sh Befehle auf entferntem System ausführen
SSHUSER="hz@artikel"
while true; do
clear
echo "(1) Plattenbelegung"
echo "(2) Aktive Benutzer"
echo "(3) Last und Prozessanzeige"
echo "(9) Ende"
echo "----------------------------------"
read -n1 -p "Aufgabe " auf
echo ""
if [ "$auf" = "9" ]; then
echo ""
echo "Programmende"
exit
elif [ "$auf" = "1" ]; then
ssh $SSHUSER df
read -p "----------- Weiter --------------" we
elif [ "$auf" = "2" ]; then
ssh $SSHUSER w
read -p "----------- Weiter --------------" we
elif [ "$auf" = "3" ]; then
ssh -t $SSHUSER htop
fi
done
Das Menü bedient die Befehle df, w und htop am entfernten Rechner. Entweder rufen Sie es in der Form bash menu.sh auf, oder Sie versehen es mit den entsprechenden Ausführungsrechten. In jedem Fall müssen Sie die hart kodierten Angaben für Benutzer und Rechner in der Variablen SSHUSER an die konkreten Gegebenheiten anpassen.
Die Optionen von read, die in diesem Skript zum Einsatz kommen, funktionieren nur mit der Bash. Mit -n1 prüft die Software die Stellenzahl der Eingabe, hier 1. Hat die Eingabe entsprechend viele Stellen, entfällt die Notwendigkeit, die Eingabetaste zu drücken.
Über den String -p "PROMPT": erzeugen Sie einen Eingabeprompt. Der Echo-Befehl sorgt dafür, dass das Skript die Eingabe des Passworts in einer neuen Zeile anfordert. Die If-Abfrage behandelt Zahlen alphanumerisch, sodass kein Fehler auftritt, wenn Sie statt Zahlen Buchstaben eingeben.
Wenn Sie ein nicht interaktives Kommando absetzen, scrollt die Anzeige durch, und das Skript legt wieder das Menü darüber. Also braucht es einen Stoppmechanismus, der einen weiteren Read-Befehl realisiert. Alternativ leiten Sie die Ausgaben an den Pager Less weiter, der von der Standardeingabe liest und den Sie über [Q] beenden.
In anderen Fällen, wie etwa beim dritten Menüpunkt, der den Befehl htop auf dem entfernten Host absetzt, erweitern Sie den Aufruf von SSH mit der Option -t. Andernfalls läuft das Skript durch, und Sie sehen wiederum nur das Menü im Terminal. Abbildung 8 zeigt das skriptgesteuerte Abarbeiten von df und den Einsatz des Stoppers.

Abbildung 8: Mit einem einfachen Skript gelingt es selbst Einsteigern, Befehle auf entfernten Rechnern abzusetzen.
Sicheres Backup
Das Shell-Skript dasi.sh aus Listing 9 hat die Aufgabe, den Inhalt eines Verzeichnisses zu sichern (hier: Daten), das auf einem anderen Rechner liegt. Dafür bieten sich verschiedene Ansätze an: eine Kombination aus SSH und Tar, der Einsatz von SSHFS und Tar oder das Kopieren mit Scp. Am Ende des Transfers schreibt die Software eine Logdatei (dasi.log).
Listing 9
#!/bin/bash # dasi.sh if [ ! -d DASI ]; then mkdir DASI fi # Log anlegen datum=$(date) touch dasi.log echo "Beginn Datensicherung: $datum" >> dasi.log echo "----------------------------------------------------" >> dasi.log # ssh + tar ssh artikel 'cd /home/hz && tar czfv - UV1' | tar xzfv - cd .. tree DASI/UV1 >> dasi.log echo "----------------------------------------------------" >> dasi.log # scp echo "Sicherung mit scp" >> dasi.log cd DASI scp -r artikel:/home/hz/UV2 . cd .. tree DASI/UV2 >> dasi.log echo "----------------------------------------------------" >> dasi.log datum=$(date) echo "Ende der Datensicherung: $datum" >> dasi.log
Welche Kombination Sie anwenden möchten, hängt vom konkreten Fall ab. Das minimale Skript ist ausbaufähig: So wäre es möglich, mithilfe eines Cronjobs Verzeichnisse zeitgesteuert außerhalb der Arbeitszeit auf eine Backup-Maschine zu übertragen. In diesem Fall käme dann aber tatsächlich nur das Authentifizieren per Schlüssel infrage statt der üblichen Eingabe eines Passworts.
Listing 9 zeigt zwei Ansätze: Zum einen sichert es das Verzeichnis UV1 mittels Kombination von Ssh und Tar ins lokale Verzeichnis DASI, zum anderen kopiert es UV2 per scp -r auf einen anderen Host. Bei letzterem Vorgehen gerät oft der Doppelpunkt nach der Kombination User@Rechner unter die Räder.
Abbildung 9 zeigt den Ablauf. Mit dem Befehl tree erzeugt das kleine Programm eine Ausgabe und schreibt diese in das Log. Das hilft dabei, den Erfolg beim Sichern zu überprüfen.

Abbildung 9: Mit dem Skript dasi.sh sichern Sie Ordner mittels verschiedener Kombinationen von SSH und weiteren Tools.
Viele Rechner
Ein Kommando auf vielen Rechnern abzusetzen – das muss kein Traum bleiben. Neben dem Einsatz von Polysh [1] und Clusterssh [2] besteht die Möglichkeit, für dieses Szenario ein Shell-Skript mit weitgehenden Funktionen zu entwerfen. Vorbereitend sollten Sie Schlüssel ohne Passwörter auf den entfernten Rechnern installieren. In Schulungsumgebungen und abgeschotteten Netzen stellt das normalerweise kein Problem dar.
Das Shellskript multi.sh aus Listing 10 fragt den Zustand des SSH-Diensts mittels systemctl auf verschiedenen Rechnern ab und führt darüber in der Logdatei multi.log Buch.
Die Zielrechner liegen in der Datei ziele.liste, in der Sie pro Zeile eine Verbindung (unter .ssh/config definiert) eintragen. Die For-Schleife liest die Datei aus, sodass das Skript an jeden Rechner das Kommando systemctl status ssh.service absetzt. Über die Ausgabeumleitung schreibt es die Resultate in die Logdatei. Am Ende geben Sie diese am Terminal aus und sehen so, wie es um den angefragten Dienst steht (Abbildung 10).
Listing 10
#!/bin/bash # multi.sh # Befehl an mehrere Rechner senden # und Logdatei anlegen touch multi.log echo "Multilog" >> multi.log echo "Start Ausführung" >> multi.log date >> multi.log for i in $(cat ziele.liste); do echo "-------------------------------------------------" >> multi.log echo "Rechner: $i" >> multi.log echo "" >> multi.log ssh -t $i systemctl status ssh.service >> multi.log done echo "------------------- E n d e ---------------------" >> multi.log
Datenverteiler
Das Skript senden.sh in Listing 11 funktioniert ganz ähnlich wie das vorige Beispiel. Diesmal geben Sie mittels Positionsparameter $1 an, welche Dateien es an die Rechner im Netzwerk verteilt. Dabei verwenden Sie die schon im vorigen Beispiel benutzte Datei ziele.liste. Unter senden.log zeichnen Sie auf, ob die Daten ankommen.
Listing 11
#! /bin/bash
# senden.sh
# Datei an mehrere Rechner senden
# Logdatei anlegen
datum=$(date)
touch senden.log
echo "Sendebericht vom $datum" >> senden.log
for i in $(cat ziele.liste); do
echo "------------------------------" >> senden.log
echo "Rechner: $i" >> senden.log
echo "" >> senden.log
scp $1 $i:/home/hz >> senden.log 2>&1
if [ $? -eq 0 ]; then
echo "ok" >> senden.log
else
echo "!!!!!! FEHLER !!!!!!!!" >> senden.log
fi
done
echo "-------- F E R T I G ---------" >> senden.log
Im Beispiel enthält die Datei nutzlast.txt die Daten, die es auf die Rechner zu verteilen gilt. Der Benutzer ist hier bereits in der Konfiguration für die Verbindung in .ssh/config eingetragen. Steht dieser Mechanismus nicht bereit, benutzen Sie die vollständige Adresse unter Angabe des Benutzers.
Als Ziele kommen in ziele.liste zwei existierende und ein fiktiver Rechner zum Einsatz. Ohne vorkonfigurierte SSH-Verbindungen müssen Sie hier die Einträge in der Form User@Rechner, beziehungsweise bei abweichenden Pfaden als User@Rechner:/Pfad vornehmen. Abbildung 11 zeigt den Ablauf mit der Log-Kontrolle.

Abbildung 11: Mit dem Skript senden.sh transferieren Sie einzelne Dateien auf einer sicheren Leitung an einen Host im Netzwerk.
Fazit
Die Secure Shell hat sich bereits in vielen Fällen als das Werkzeug für den Zugriff auf entfernte Systeme bewährt. Dabei verbindet sie die Vorzüge starker Kryptografie mit zahlreichen Features, die den Einsatz im Alltag sinnvoll und vor allem komfortabel machen. In Kombination mit weiteren Werkzeugen wie Tar oder FUSE erstellen Sie so mit wenigen Zeilen Code eine einfache Backup-Lösung oder greifen transparent auf die Daten eines entfernten Systems zu.
Glossar
-
Chroot
-
Change Root. Eine Umgebung, meist in Form einer Verzeichnisstruktur oder eines Containers, die aus Sicht des Anwenders ein komplettes System enthält, tatsächlich aber nur in einem Teilbaum des Hosts oder der virtuellen Maschine liegt.
Infos
-
Polysh: http://guichaz.free.fr/polysh/
-
Clusterssh: https://github.com/duncs/clusterssh/wiki








