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;');
}
?>
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?