blog.bartlweb - a technologist's external brain

Befehle auf Remote-Systemen mittels SSH-Verbindung über PHP absetzen

"Ein Verwaltungsinterface auf einem Gatewayrechner für interne Systeme", "das Deployen von generierten Konfigurationsdateien", "den Status eines Drittsystems erfassen", ... es gibt unzählige Anwendungsfälle, in denen es notwendig werden kann sich per PHP-Skript und SSH auf ein entferntes System zu verbinden und dort Befehle abzusetzen.

Die Library phpseclib (phpseclib.sourceforge.net) ermöglicht es, aus PHP-Skripten heraus, SSH-Verbindungen aufzubauen und Befehle abzusetzen.

Authentifizierung mit Benutzername und Passwort

Die einfachere Variante ist die Authentifizierung mit Benutzername und Passwort am entfernten System. Hierfür reicht bereits das Einbinden der Library und wenige Zeilen Code aus.

<?php
 
// include library
set_include_path('phpseclib');
include('Net/SSH2.php');
 
// connection parameters
$config = array(
    'host' => '192.168.0.1',
    'port' => '22',
    'username' => 'testuser',
    'password' => 'strongpassword',
);
 
// connect
$ssh = new Net_SSH2($config['host'] . ':' . $config['port']);
 
if (!$ssh->login($config['username'], $config['password'])) {
    echo('Login via ssh at host ' . $config['host'] . ' failed.');
} else {
    echo $ssh->exec('uname -a; whoami;');
}
 
?>

Authentifizierung mittels Public-Key

Die Library phpseclib unterstützt nicht nur die Anmeldung mittels Passwort, sondern auch mittels Public-Key. Dazu muss am Rechner, der die Verbindung aufbauen möchte (also in diesem Fall der Webserver auf dem das PHP-Skript läuft), ein privater Schlüssel und ein dazugehöriger öffentlicher Schlüssel erstellt werden. Der öffentliche Schlüssel wird in der Datei authorized_keys im Home-Verzeichnis des Nutzers (/home/<user>/.ssh/authorized_keys) mit dem man sich am entfernten System autorisieren möchte hinterlegt. Bei der Anmeldung werden dann die Schlüssel abgeglichen und so festgestellt, ob das Gegenüber autorisiert ist.

PHP-Skript zum Erzeugen der notwendigen Schlüssel

<?php
 
// include library
set_include_path('phpseclib');    
include('Crypt/RSA.php');
 
// generate key
$rsa = new Crypt_RSA();
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_OPENSSH);
extract($rsa->createKey(2048));
 
// print key
echo $privatekey;
echo "\r\n";
echo $publickey;
 
?> 

Das Skript gibt die beiden Schlüssel aus, die Sie dann als ssh_rsa und ssh_rsa.pub am Server ablegen.

Achten Sie darauf, die Schlüssel so abzulegen, dass diese zwar von PHP gelesen aber nicht in einem öffentlichen Verzeichnis des Webservers landen, sonst könnten Angreifer die Schlüssel abrufen und damit ebenfalls Verbindungen zum Zielhost aufbauen.

Beispiel für den Verbindungsaufbau

 <?php
 
// include library
set_include_path('phpseclib');
include('Net/SSH2.php');
include('Crypt/RSA.php');
 
// connection parameters
$config = array(
    'host' => '192.168.0.1',
    'port' => '22',
    'username' => 'testuser',
    'privatekey' => '/path/to/id_rsa',
);
 
// connect
$ssh = new Net_SSH2($config['host'] . ':' . $config['port']);
$key = new Crypt_RSA();
$key->loadKey(file_get_contents($config['privatekey']));
 
if (!$ssh->login($config['username'], $key)) {
    echo('Login via ssh at host ' . $config['host'] . ' failed.');
} else {
    echo $ssh->exec('uname -a; whoami;');
}
 
?>

Dieser Artikel hat Dir deinen Tag gerettet?

... und mühevolles Probieren, Recherchieren und damit Stunden an Zeit gespart? Oder einfach nur Dein Problem gelöst?

Dann würde ich mich freuen, wenn Du meine Zeit für die Erstellung dieses Blogartikels mit einer kleinen Anerkennung honorierst:

Zahlung mit PayPal oder Kreditkarte.

Hinweis zur Verwendung

Die Übermittlung einer Zahlung ist eine persönliche Anerkennung Ihrerseits an den Entwickler (Christian Bartl, Privatperson). Eine Zahlung ist nicht zweckgebunden und es ist keine Gegenleistung zu erwarten. Bitte beachten Sie, dass für eine übermittelte Zahlung keine Quittung ausgestellt werden kann.

Über den Autor

Christian Bartl

Christian Bartl Requirements Engineer
& Solution Architect für Online und Mobile

Als Technologie-Enthusiast und begeisterter Programmierer entwickle ich in meiner Freizeit Websites, Software und IT-Lösungen, die mir selbst und anderen den Alltag vereinfachen.

mehr auf christian.bartl.me

Kommentare

  1. Hey,

    wenn ich den Dateipfad bei
    'privatekey' => '/path/to/id_rsa',
    ''privatekey' => '/home/user/.ssh/id_rsa'

    angebe, kommt bei
    $key->loadKey(file_get_contents($config['privatekey']));

    im Browser "Failed to Open Stream"

    Die Datei existiert, der Pfad ist korrekt.

    Wo liegt der Fehler?

    kommentieren

    1. Hallo FF2021,
      damit die Funktion file_get_contents genutzt werden kann, muss in der php.ini-Konfigurationsdatei die Direktive allow_url_fopen gesetzt sein.
      lg Christian

      kommentieren

Kommentar schreiben

Der hier angegebene Name wird gemeinsam mit deinem Kommentar auf der Website veröffentlicht.

Deine E-Mail-Adresse wird zur einmaligen Benachrichtigung bei Veröffentlichung des Kommentars genutzt.

Benachrichtigung per E-Mail über Antworten auf meinen Kommentar erhalten.

Bitte tippe die Zahlenkombination "4331" ein, nur dann kann ich deinen Kommentar entgegennehmen.

Bitte fülle dieses Feld nicht aus, nur dann kann ich deinen Kommentar entgegennehmen.