Je cherche à établir une connexion SSH via PHP. Quelle est la meilleure façon de procéder ? Je sais que je peux le faire :
shell_exec("SSH user@host.com mkdir /testing");
Rien de mieux ? C'est tellement "coquin" :).
Je cherche à établir une connexion SSH via PHP. Quelle est la meilleure façon de procéder ? Je sais que je peux le faire :
shell_exec("SSH user@host.com mkdir /testing");
Rien de mieux ? C'est tellement "coquin" :).
J'utiliserais phpseclib, une implémentation SSH purement PHP . Un exemple :
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
echo $ssh->exec('pwd');
echo $ssh->exec('ls -la');
?>
Peuvent-ils être asynchrones ? J'ai besoin de parler à plusieurs systèmes à la fois - puis-je lancer plusieurs sessions ssh et ensuite "sélectionner" (ou interroger) sur tous ces systèmes ?
Kinda. Vraiment, ta question serait plus appropriée en tant que nouvelle question qu'en tant que réponse, mais peu importe. Vous pourriez faire $ssh->setTimeout(...)
pour chaque instance de $ssh et les parcourir. Le mode interactif pourrait être meilleur pour vous aussi, car la lecture et l'écriture y sont en quelque sorte disjointes. De la même manière, vous pouvez utiliser enablePTY() pour utiliser $ssh->exec()
con $ssh->read()
/ $ssh->write()
.
Je ne pense pas que SFTP, en tant que protocole, supporte readlink(). Si vous connaissez des implémentations SFTP qui supportent readlink(), je serais curieux de les connaître.
Disposez-vous de l'extension SSH2 ?
Docs : http://www.php.net/manual/en/function.ssh2-exec.php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$stream = ssh2_exec($connection, '/usr/local/bin/php -i');
Je n'arrive pas à faire fonctionner le module SSH2, j'obtiens le résultat suivant dans le journal des erreurs : PHP Warning:Démarrage de PHP : ssh2 : Unable to initialize module Module compilé avec le module API=20050922 PHP compilé avec le module API=20090626 Ces options doivent correspondre dans Unknown on line 0
Notez également que vous devez avoir OpenSSL et libssh2 pour que le module ssh2 fonctionne correctement. Si vous compilez manuellement PHP, vous devez vous assurer que vous avez des versions compatibles des deux modules requis. Cette erreur indique un désaccord entre les versions.
J'ai eu du mal avec ssh2 en php, principalement parce que le flux de sortie fonctionne parfois et parfois non. Je vais juste coller ma librairie ici qui fonctionne très bien pour moi. S'il y a de petites incohérences dans le code, c'est parce que je l'ai inséré dans un framework, mais vous devriez pouvoir le porter sans problème :
<?php
class Components_Ssh {
private $host;
private $user;
private $pass;
private $port;
private $conn = false;
private $error;
private $stream;
private $stream_timeout = 100;
private $log;
private $lastLog;
public function __construct ( $host, $user, $pass, $port, $serverLog ) {
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$this->port = $port;
$this->sLog = $serverLog;
if ( $this->connect ()->authenticate () ) {
return true;
}
}
public function isConnected () {
return ( boolean ) $this->conn;
}
public function __get ( $name ) {
return $this->$name;
}
public function connect () {
$this->logAction ( "Connecting to {$this->host}" );
if ( $this->conn = ssh2_connect ( $this->host, $this->port ) ) {
return $this;
}
$this->logAction ( "Connection to {$this->host} failed" );
throw new Exception ( "Unable to connect to {$this->host}" );
}
public function authenticate () {
$this->logAction ( "Authenticating to {$this->host}" );
if ( ssh2_auth_password ( $this->conn, $this->user, $this->pass ) ) {
return $this;
}
$this->logAction ( "Authentication to {$this->host} failed" );
throw new Exception ( "Unable to authenticate to {$this->host}" );
}
public function sendFile ( $localFile, $remoteFile, $permision = 0644 ) {
if ( ! is_file ( $localFile ) ) throw new Exception ( "Local file {$localFile} does not exist" );
$this->logAction ( "Sending file $localFile as $remoteFile" );
$sftp = ssh2_sftp ( $this->conn );
$sftpStream = @fopen ( 'ssh2.sftp://' . $sftp . $remoteFile, 'w' );
if ( ! $sftpStream ) {
// if 1 method failes try the other one
if ( ! @ssh2_scp_send ( $this->conn, $localFile, $remoteFile, $permision ) ) {
throw new Exception ( "Could not open remote file: $remoteFile" );
}
else {
return true;
}
}
$data_to_send = @file_get_contents ( $localFile );
if ( @fwrite ( $sftpStream, $data_to_send ) === false ) {
throw new Exception ( "Could not send data from file: $localFile." );
}
fclose ( $sftpStream );
$this->logAction ( "Sending file $localFile as $remoteFile succeeded" );
return true;
}
public function getFile ( $remoteFile, $localFile ) {
$this->logAction ( "Receiving file $remoteFile as $localFile" );
if ( ssh2_scp_recv ( $this->conn, $remoteFile, $localFile ) ) {
return true;
}
$this->logAction ( "Receiving file $remoteFile as $localFile failed" );
throw new Exception ( "Unable to get file to {$remoteFile}" );
}
public function cmd ( $cmd, $returnOutput = false ) {
$this->logAction ( "Executing command $cmd" );
$this->stream = ssh2_exec ( $this->conn, $cmd );
if ( FALSE === $this->stream ) {
$this->logAction ( "Unable to execute command $cmd" );
throw new Exception ( "Unable to execute command '$cmd'" );
}
$this->logAction ( "$cmd was executed" );
stream_set_blocking ( $this->stream, true );
stream_set_timeout ( $this->stream, $this->stream_timeout );
$this->lastLog = stream_get_contents ( $this->stream );
$this->logAction ( "$cmd output: {$this->lastLog}" );
fclose ( $this->stream );
$this->log .= $this->lastLog . "\n";
return ( $returnOutput ) ? $this->lastLog : $this;
}
public function shellCmd ( $cmds = array () ) {
$this->logAction ( "Openning ssh2 shell" );
$this->shellStream = ssh2_shell ( $this->conn );
sleep ( 1 );
$out = '';
while ( $line = fgets ( $this->shellStream ) ) {
$out .= $line;
}
$this->logAction ( "ssh2 shell output: $out" );
foreach ( $cmds as $cmd ) {
$out = '';
$this->logAction ( "Writing ssh2 shell command: $cmd" );
fwrite ( $this->shellStream, "$cmd" . PHP_EOL );
sleep ( 1 );
while ( $line = fgets ( $this->shellStream ) ) {
$out .= $line;
sleep ( 1 );
}
$this->logAction ( "ssh2 shell command $cmd output: $out" );
}
$this->logAction ( "Closing shell stream" );
fclose ( $this->shellStream );
}
public function getLastOutput () {
return $this->lastLog;
}
public function getOutput () {
return $this->log;
}
public function disconnect () {
$this->logAction ( "Disconnecting from {$this->host}" );
// if disconnect function is available call it..
if ( function_exists ( 'ssh2_disconnect' ) ) {
ssh2_disconnect ( $this->conn );
}
else { // if no disconnect func is available, close conn, unset var
@fclose ( $this->conn );
$this->conn = false;
}
// return null always
return NULL;
}
public function fileExists ( $path ) {
$output = $this->cmd ( "[ -f $path ] && echo 1 || echo 0", true );
return ( bool ) trim ( $output );
}
}
Pour ceux qui utilisent le Symfony cadre, le site phpseclib peut également être utilisé pour se connecter via SSH. Il peut être installé à l'aide de composer :
composer require phpseclib/phpseclib
Ensuite, il suffit de l'utiliser comme suit :
use phpseclib\Net\SSH2;
// Within a controller for example:
$ssh = new SSH2('hostname or ip');
if (!$ssh->login('username', 'password')) {
// Login failed, do something
}
$return_value = $ssh->exec('command');
Télécharger phpseclib v1 et utilisez ce code :
<?php
set_include_path(__DIR__ . '/phpseclib1.0.11');
include("Net/SSH2.php");
$key ="MyPassword";
/* ### if using PrivateKey ###
include("Crypt/RSA.php");
$key = new Crypt_RSA();
$key->loadKey(file_get_contents('private-key.ppk'));
*/
$ssh = new Net_SSH2('www.example.com', 22); // Domain or IP
if (!$ssh->login('your_username', $key)) exit('Login Failed');
echo $ssh->exec('pwd');
?>
Téléchargement le plus récent phpseclib v2 (nécessite composer install
au début) :
<?php
set_include_path($path=__DIR__ . '/phpseclib-master/phpseclib');
include ($path.'/../vendor/autoload.php');
$loader = new \Composer\Autoload\ClassLoader();
use phpseclib\Net\SSH2;
$key ="MyPassword";
/* ### if using PrivateKey ###
use phpseclib\Crypt\RSA;
$key = new RSA();
$key->load(file_get_contents('private-key.ppk'));
*/
$ssh = new SSH2('www.example.com', 22); // Domain or IP
if (!$ssh->login('your_username', $key)) exit('Login Failed');
echo $ssh->exec('pwd');
?>
p.s. si vous obtenez "Connection timed out" alors c'est probablement le problème de HOST/FIREWALL (local ou distant) ou similaire, pas une faute de script.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
0 votes
Puis-je savoir pourquoi vous pensez que ce n'est pas le meilleur moyen de sécurité ? Je suis curieux !