Paramiko öffnet SSH-Verbindungen - Abhörsicher

Lesezeit
4 Minuten
Bis jetzt gelesen

Paramiko öffnet SSH-Verbindungen - Abhörsicher

07.11.2012 - 12:29
Veröffentlicht in:

Im Python-Universum finden sich nützliche Module für jeden Zweck. Mit dem Paramiko-Modul können Python-Programmierer und Administratoren per SSH auf entfernten Rechnern Kommandos ausführen und sicher Dateien übertragen.

Seit die Secure Shell (SSH) vor vielen Jahren einmal Telnet abgelöst hat, kommt kein Administrator mehr ohne sie aus. Um sich in Python-Skripts per SSH mit anderen Rechnern zu verbinden und dort Befehle auszuführen, gibt es eine Reihe von Lösungen [1]. Die bewährteste von ihnen ist das Paramiko-Modul, das dieser Artikel näher vorstellt [2].

Ursprünglich wurde Paramiko von Robey Pointer geschrieben, der unter anderem bei Twitter gearbeitet und dort Open-Source-Software in Scala unter einer freien Lizenz veröffentlicht hat [3]. Ein Python-Modul mit dem Namen "ssh" firmierte als Fork von Paramiko einige Zeit als dessen Nachfolger. Mittlerweile sind die beiden Projekte aber unter dem Originalnamen vereint, und Jeff Forcier hat die Leitung der Entwicklung übernommen. Der aktuellste Code findet sich deshalb auf [4] und Forciers Github-Seite [5], die ausführliche API-Dokumentation aber immer noch unter [2].

 

Überall zu Hause

 

Empfohlen wird für die aktuelleste Paramiko-Version (derzeit 1.8.0) die Python-Distribution 2.3 oder neuer, der Support für Python 3 ist noch in Arbeit. Viele Linux-Distributionen bringen zumindest ältere Versionen von Paramiko schon mit, ebenso wie etwa FreeBSD.

Aus dem entpackten Tar-Archiv lässt sich Paramiko als Root systemweit mit dem Befehl easy_install ./ installieren. Auch eine Installation auf Windows-Betriebssystemen ist möglich, sie setzt jedoch neben Python die vorherige Installation von Pycrypt, am besten als Binärpaket von [6], voraus.

Im einfachsten Fäll lässt sich Paramiko zum Einloggen auf einem Rechner mit nur wenigen Zeilen einsetzen. Nach dem obligatorischen Importieren des Modules erzeugt die Methode SSHClient ein neues Client-Objekt, das mit der Methode connect() die Verbindung herstellt:

import paramiko
ssh = paramiko.SSHClient()
ssh.connect(Host, username=Username, password=Passwort)

Typischerweise funktioniert das aber nicht, sondern erzeugt eine SSHException. Der Grund dafür ist, dass Paramiko wie der Standard-SSH-Client den Host-Key des entfernten Rechners prüft. Weil das Modul aber ohne Weiteres keinen Zugang zu den gespeicherten Host-Keys hat, schlägt der Verbindungsversuch fehl. Ein einfacher Workaround besteht darin, Paramiko bislang unbekannte Host-Keys umstandslos eintragen zu lassen.

ssh.set_missing_host_key_policy(
 paramiko.AutoAddPolicy())

Dies ist natürlich aber nicht im Sinn des Erfinders und tendenziell unsicher, sollte also nur bei Tests in sicheren Netzen verwendet werden. Der korrekte Weg besteht darin, Paramiko die Host-Keys laden zu lassen, auf dass es sie wie gedacht prüfen kann. Dazu dient die Funktion load_host_keys():

client.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))

Setzt man diese Zeile im obigen Beispiel vor den Connect-Aufruf, dürfte die Verbindung klappen. Manche Administratoren haben aber aus Sicherheitsgründen auch das SSH-Login per Username und Passwort abgeschaltet und erlauben lediglich die Authentifizierung per Public Key. Wenn der Anwender zur Verwaltung der Private Keys einen SSH-Agent verwendet, macht Paramiko davon Gebrauch. Hat er die Passphrase bisher noch nicht eingegeben, öffnet sich auf Desktop-Linux-Systemen ein Dialog der zur Eingabe auffordert.

Als Parameter muss client.connect() dann nur der username übergeben werden. Hat man einen sogenannten Channel für die SSH-Verbindung, lassen sich mit exec_command() auf dem entfernten Rechner Befehle ausführen. Der Aufruf gibt jeweils einen Dateideskriptor für die Standardeingabe, die Standardausgabe und die Fehlerausgabe zurück. Listing 1 zeigt dafür ein Beispiel, das die Prozesstabelle auf dem entfernten Rechner ausgibt.

Listing 1

Prozesstabelle anzeigen

01 import os
02 import sys
03 import paramiko
04
05 hostkeytype = None
06 hostkey = None
07 hostname = "server.domain.net"
08
09 client = paramiko.SSHClient()
10 client.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
11 client.connect(hostname, username="ofrommel")
12 stdin, stdout, stderr = client.exec_command('ps -a')
13 for line in stdout:
14         print line.strip('\n')
15 client.close()

Wer das Default-Verhalten, den Agent zu verwenden, abschalten will, kann der Methode allow_agent=False übergeben.

Wer den SSH-Agent nicht verwenden kann oder will, muss sich anders behelfen. Paramiko bietet an, den zum Public Key (der auf dem Server liegt) passenden Private Key selbst zu laden. Dies geht einfach mit der Funktion

pkey = paramiko.RSAKey.from_private_key(pkey_file)

Es funktioniert aber nur, wenn der Private Key nicht mit einer Passphrase geschützt ist. Ist er dies aber, wie etwa dieser Key,

more ~/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED

muss man der obigen Methode die Passphrase als zweites Argument übergeben. Der Code in Abbildung 1 zeigt, wie man die Passphrase von der Standardeingabe liest und den Private Key damit entschlüsselt, bevor man ihn an die Connect-Methode übergibt. Dabei darf man nicht vergessen, das die Eingabe abschließende Linefeed-Zeichen zu entfernen, sonst schlägt die Dekodierung fehl.

Abbildung 1: Paramiko verwendet die Keys des SSH-Agents, kann aber den Private Key auch selbst dekodieren.
Abbildung 1: Paramiko verwendet die Keys des SSH-Agents, kann aber den Private Key auch selbst dekodieren.

 

Neben solchen SSH-Sessions deckt Paramiko auch die Datenübertragung per SFTP ab. Um eine entsprechende Verbindung zu öffnen, genügt es, die Methode open_sftp() des Paramiko-Clients aufzurufen, was wiederum ein SFTP-Objekt zurückliefert. Dieses Objekt bietet eine ganze Reihe von Methoden, die Shell-Befehlen oder den bekannten Kommandos in FTP-Clients ähneln. So wechselt chdir() in ein anderes Verzeichnis und listdir() gibt den Inhalt eines Verzeichnisses aus.

Es lassen sich aber auch Verzeichnisse anlegen, löschen und umbenennen. Dies übernehmen die Methoden mkdir(), rmdir() und rename(). Eine Datei löscht ein Aufruf von remove() oder unlink().

Auch für das Ändern des Dateieigentümers und der Zugriffsrechte bietet der SFTP-Client passende Methoden. Dies sind wie in der Shell chown() und chmod(). Die beiden Methoden get() und put() holen eine Datei vom Server respektive speichern sie dort.

Schließlich lässt sich eine Datei auch direkt auf dem Server anlegen, wenn man file() verwendet. So können Python-Skripts umstandslos Dateien auf dem Server speichern, ohne vorher lokal eine temporäre Kopie davon anzulegen. Eine vollständige Liste aller Funktionen findet sich in der API-Dokumentation des SFTPClient-Objekts unter [2].

Einfacher

Wem dies alles noch zu viel Aufwand ist, der sollte einen Blick auf den Paramiko-Wrapper eines Python-Anwenders verwenden, der sich online nur unter seinem Vornamen Zeth auftritt [7]. Mit seinem Modul gestaltet sich die Benutzung von SSH und SFTP per Python noch einmal einfacher:

import ssh
s = ssh.Connection('my.server.de')
s.put('up.txt')
s.get('down.txt')
s.execute('du -h .')

Der Wrapper ist natürlich nicht so gut getestet wie Paramiko selbst, und man hat weniger Kontrolle darüber, was hinter den Kulissen passiert.

Obligatorisch

Wer mit Python-Skripts per SSH auf andere Rechner zugreifen, dabei Kommandos ausführen oder Dateien übertragen will, kommt an Paramiko kaum vorbei. Das Modul hat eine lange Geschichte, viele Anwender und ist entsprechend gut getestet. Es arbeitet mit SSH-Agents zusammen, bietet auf Wunsch eigenes Key-Handling und ist im Detail konfigurierbar. Seit es Ende September 2012 einen neuen Maintainer gefunden hat, ist nun auch seine Zukunft gesichert.

Ähnliche Beiträge

Im Test: Auerswald COMtrexx Next Redaktion IT-A… Mo., 25.03.2024 - 07:34
Telefonie ist zu einem IT-Thema geworden und dank ausgereifter Bereitstellungs- und Konfigurationsmöglichkeiten müssen sich auch Telefonie-unerfahrene Admins oder IT-Techniker vor deren Einsatz nicht sorgen. Telefonanlagen selbst haben nunmehr minimale Abmessungen erreicht, wie unser Blick auf die COMtrexx Next von Auerswald zeigt.

Mehr Datensicherheit durch ganzheitliche Plattformen

Die Folgen von Cyberangriffen sind für Unternehmen verheerend. Dies gilt vor allem für Attacken auf hybride IT-Umgebungen, die Datenverluste auf mehreren Plattformen zur Folge haben. Deshalb lohnt es sich, auf ganzheitliche Werkzeuge für eine sichere Kommunikation und Datenübertragung zu setzen. Welchen maßgeblichen Beitrag Produktivitätsplattformen in den Bereichen Verwaltung, Kosteneffizienz und Reaktionsschnelligkeit leisten, erklärt unser Artikel.