ssh2_connect

(PECL ssh2 >= 0.9.0)

ssh2_connectПодключение к SSH-серверу

Описание

ssh2_connect(
    string $host,
    int $port = 22,
    array $methods = ?,
    array $callbacks = ?
): resource|false

Устанавливает соединение с сервером по SSH.

После соединения, пользователь должен проверить ключ сервера, используя функцию ssh2_fingerprint(), и после этого авторизоваться, используя пароль или открытый ключ.

Список параметров

host

port

methods

Параметр methods может быть ассоциативным массивом, содержащим до четырёх записей, перечисленных ниже.

Параметр methods может быть ассоциативным массивом, содержащим от одного до четырёх параметров
Индекс Что обозначает Допустимые значения*
kex Список методов обмена ключами, разделённых запятой, в порядке предпочтения. diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, и diffie-hellman-group-exchange-sha1
hostkey Список методов ключей хоста, разделённых запятой, в порядке предпочтения. ssh-rsa и ssh-dss
client_to_server Ассоциативный массив, содержащий настройки шифрования, сжатия и метода имитовставки ("message authentication code" или MAC) для сообщений, отправленных клиентом серверу.  
server_to_client Ассоциативный массив, содержащий настройки шифрования, сжатия и метода имитовставки ("message authentication code" или MAC) для сообщений, отправленных сервером клиенту.  

* - Поддерживаемые значения зависят от методов, поддерживаемых базовой библиотекой. Более подробно читайте документацию по » libssh2.

client_to_server и server_to_client могут быть ассоциативными массивами, содержащими любой или же все нижеперечисленные параметры.
Индекс Что обозначает Допустимые значения*
crypt Список методов шифрования, разделённых запятой, в порядке предпочтения. rijndael-cbc@lysator.liu.se, aes256-cbc, aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, arcfour и none**
comp Список методов сжатия, разделённых запятой, в порядке предпочтения. zlib и none
mac Список методов MAC, разделённых запятой, в порядке предпочтения. hmac-sha1, hmac-sha1-96, hmac-ripemd160, hmac-ripemd160@openssh.com и none**

Замечание: Метод шифрования "none" и MAC

В целях безопасности none отключён в базовой библиотеке » libssh2, если вы не разрешили его самостоятельно на этапе сборки, используя соответствующие ключи ./configure. Смотрите документацию по базовой библиотеки для более подробной информации.

callbacks

callbacks может быть ассоциативным массивом, содержащим любой или же все нижеперечисленные параметры

Параметры callback-функции
Индекс Что обозначает Прототип
ignore Имя функции, вызываемой после получения пакета SSH2_MSG_IGNORE void ignore_cb($message)
debug Имя функции, вызываемой после получения пакета SSH2_MSG_DEBUG void debug_cb($message, $language, $always_display)
macerror Имя функции, вызываемой если пакет получен, но MAC не удался. Если callback-функция вернёт true, несовпадение будет проигнорировано, в обратном случае соединение будет оборвано. bool macerror_cb($packet)
disconnect Имя функции, вызываемой после получения пакета SSH2_MSG_DISCONNECT void disconnect_cb($reason, $message, $language)

Возвращаемые значения

Возвращает ресурс в случае успешного выполнения или false в случае возникновения ошибки.

Примеры

Пример #1 Пример ssh2_connect()

Откроем соединение, принудительно используя такие настройки: 3des-cbc при отправке пакетов, шифр aes любой силы при получении пакетов, без сжатия в обоих направлениях и обмен ключами Group1.

<?php
/* Оповещаем пользователя, если сервер прервал соединение */
function my_ssh_disconnect($reason, $message, $language) {
printf("Сервер отключился с кодом причины [%d] и сообщением: %s\n",
$reason, $message);
}

$methods = array(
'kex' => 'diffie-hellman-group1-sha1',
'client_to_server' => array(
'crypt' => '3des-cbc',
'comp' => 'none'),
'server_to_client' => array(
'crypt' => 'aes256-cbc,aes192-cbc,aes128-cbc',
'comp' => 'none'));

$callbacks = array('disconnect' => 'my_ssh_disconnect');

$connection = ssh2_connect('shell.example.com', 22, $methods, $callbacks);
if (!
$connection) die('Не удалось установить соединение');
?>

Смотрите также

  • ssh2_fingerprint() - Получение отпечатка удалённого сервера
  • ssh2_auth_none() - Аутентификация как "none"
  • ssh2_auth_password() - Аутентификация через SSH с использованием обычного пароля
  • ssh2_auth_pubkey_file() - Аутентификация с открытым ключом
  • ssh2_disconnect() - Закрыть соединение с удалённым сервером SSH

add a note add a note

User Contributed Notes 8 notes

up
43
Steve Kamerman
13 years ago
Due to a lack of complete examples, here's a simple SSH2 class for connecting to a server, authenticating with public key authentication, verifying the server's fingerprint, issuing commands and reading their STDOUT and properly disconnecting.  Note: You may need to make sure you commands produce output so the response can be pulled.  Some people suggest that the command is not executed until you pull the response back.
<?php
class NiceSSH {
   
// SSH Host
   
private $ssh_host = 'myserver.example.com';
   
// SSH Port
   
private $ssh_port = 22;
   
// SSH Server Fingerprint
   
private $ssh_server_fp = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
   
// SSH Username
   
private $ssh_auth_user = 'username';
   
// SSH Public Key File
   
private $ssh_auth_pub = '/home/username/.ssh/id_rsa.pub';
   
// SSH Private Key File
   
private $ssh_auth_priv = '/home/username/.ssh/id_rsa';
   
// SSH Private Key Passphrase (null == no passphrase)
   
private $ssh_auth_pass;
   
// SSH Connection
   
private $connection;
   
    public function
connect() {
        if (!(
$this->connection = ssh2_connect($this->ssh_host, $this->ssh_port))) {
            throw new
Exception('Cannot connect to server');
        }
       
$fingerprint = ssh2_fingerprint($this->connection, SSH2_FINGERPRINT_MD5 | SSH2_FINGERPRINT_HEX);
        if (
strcmp($this->ssh_server_fp, $fingerprint) !== 0) {
            throw new
Exception('Unable to verify server identity!');
        }
        if (!
ssh2_auth_pubkey_file($this->connection, $this->ssh_auth_user, $this->ssh_auth_pub, $this->ssh_auth_priv, $this->ssh_auth_pass)) {
            throw new
Exception('Autentication rejected by server');
        }
    }
    public function
exec($cmd) {
        if (!(
$stream = ssh2_exec($this->connection, $cmd))) {
            throw new
Exception('SSH command failed');
        }
       
stream_set_blocking($stream, true);
       
$data = "";
        while (
$buf = fread($stream, 4096)) {
           
$data .= $buf;
        }
       
fclose($stream);
        return
$data;
    }
    public function
disconnect() {
       
$this->exec('echo "EXITING" && exit;');
       
$this->connection = null;
    }
    public function
__destruct() {
       
$this->disconnect();
    }
}
?>

[EDIT BY danbrown AT php DOT net: Contains two bugfixes suggested by 'AlainC' in user note #109185 (removed) on 26-JUN-2012.]
up
18
thessoro at gmail dot com
9 years ago
Be careful when providing a specific hostkey order.

<?php
ssh2_connect
('IP', 'port', array('hostkey'=>'ssh-rsa, ssh-dss'));
?>

Will only work when the public key of the server is RSA, and not DSA also as expected. This is caused by the empty space before the "ssh-dss".

So a similar code:

<?php
ssh2_connect
('IP', 'port',   array('hostkey'=>'ssh-rsa,ssh-dss'));
?>

Will work. The HOSTKEY method is overriden using exactly what you write, so no empty spaces are allowed.

This took me some time that you could save ;)
up
3
jrdbrndt at gmail dot com
4 years ago
Trying to include "aes256-cbc" in the encryption methods list caused an error. The documentation here may be out of date, and you might find a more accurate list of what values are acceptable by checking the libssh2 documentation at libssh2.org.
up
11
christophermjgray at gmail dot com
7 years ago
This page is out of date.  Any of the SHA-1 in the Key Exchange Methods in the kex section should be discarded, due to Logjam (https://weakdh.org/logjam.html).  If you continue to use them, connects will result in the following warning:
"Warning: ssh2_connect(): Error starting up SSH connection(-5): Unable to exchange encryption keys in ..."

The following is an example of what works.  Also by removing the 'hex' section all together, results in libssl (https://libssh2.org/) falling back to discovering which is the strongest cipher to authenticate with.

<?php

if (!function_exists("ssh2_connect")) die("function ssh2_connect doesn't exist");

function
ssh2_debug($message, $language, $always_display) {
  
printf("%s %s %s\n",$message,$language,$always_display);
}

/* Notify the user if the server terminates the connection */
function my_ssh_disconnect($reason, $message, $language) {
 
printf("Server disconnected with reason code [%d] and message: %s\n", $reason, $message);
}

$methods = array(
   
'hostkey'=>'ssh-rsa,ssh-dss',
//    'kex' => 'diffie-hellman-group-exchange-sha256',
   
'client_to_server' => array(
       
'crypt' => 'aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-cbc,blowfish-cbc',
       
'comp' => 'none'),
   
'server_to_client' => array(
       
'crypt' => 'aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-cbc,blowfish-cbc',
       
'comp' => 'none'));
       
$callbacks = array('disconnect' => 'my_ssh_disconnect');

foreach (array(
'192.168.1.1') as $host) {
 
$connection = ssh2_connect($host, 22, $methods, $callbacks);
  if (!
$connection) die("Connection failed:");

 
ssh2_auth_password($connection, 'user', 'my_password') or die("Unable to authenticate");
 
$stream = ssh2_exec($connection, 'free -m');
 
stream_set_blocking($stream, true);
 
$stream_out = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
  echo
stream_get_contents($stream_out);
}

?>
up
1
Trev White
11 years ago
Hi,
If you are having problems with running a ssh2 session and it waits forever during the execution of stream_get_contents, it might be because the remote system has run the command and is now sitting at a # prompt waiting for the next command.  I had this issue on a HP MSA box, here is the code to get around the issue.

Assuming you are connected with your authentication method and $ssh contains the handle.

<?php
$command
= "check disk";
// Open a nice large window to stop wrapping
$stream = ssh2_shell ($ssh, 'xterm', null, 200, 200, SSH2_TERM_UNIT_CHARS);

// Hook into the error stream
$errorStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR); 

// Block the streams so we wait until they complete
stream_set_blocking ($stream, true);
stream_set_blocking($errorStream, true);

// Send the commands to the terminal
fwrite ($stream, $command . PHP_EOL );

// Wait give the terminal a chance to accept and start processing the command, this is a slow storage device after all
sleep(2);

// IMPORTANT BIT!!  Send exit to the terminal to close the connection BEFORE WE WAIT FOR THE STREAM
fwrite ($stream, "exit" . PHP_EOL );
sleep (2);

// Print the output
echo stream_get_contents($stream);
$errortext=stream_get_contents($errorStream);

if (
strlen($errortext) > 0) {
         
// Error Data
        
echo "Error Data: $errortext";
         exit (
1);
}

// All Good
exit (0);

?>

You can't use ssh2_exec with this method (well at lease I couldn't) because on executing the first command the stream gets blocked and then you can't run the exit command, whereas a terminal seems to use one session.

I hope this helps someone.
up
1
suri dot suribala dot com
19 years ago
With Sara's help, I have the following SS2 class that is quite flexible. If anyone improves it, please feel free to let me know.

<?php

// ssh protocols
// note: once openShell method is used, cmdExec does not work

class ssh2 {

  private
$host = 'host';
  private
$user = 'user';
  private
$port = '22';
  private
$password = 'password';
  private
$con = null;
  private
$shell_type = 'xterm';
  private
$shell = null;
  private
$log = '';

  function
__construct($host='', $port=''  ) {

     if(
$host!='' ) $this->host  = $host;
     if(
$port!='' ) $this->port  = $port;

    
$this->con  = ssh2_connect($this->host, $this->port);
     if( !
$this->con ) {
      
$this->log .= "Connection failed !";
     }

  }

  function
authPassword( $user = '', $password = '' ) {

     if(
$user!='' ) $this->user  = $user;
     if(
$password!='' ) $this->password  = $password;

     if( !
ssh2_auth_password( $this->con, $this->user, $this->password ) ) {
      
$this->log .= "Authorization failed !";
     }

  }

  function
openShell( $shell_type = '' ) {

        if (
$shell_type != '' ) $this->shell_type = $shell_type;
   
$this->shell = ssh2_shell( $this->con$this->shell_type );
    if( !
$this->shell ) $this->log .= " Shell connection failed !";

  }

  function
writeShell( $command = '' ) {

   
fwrite($this->shell, $command."\n");

  }

  function
cmdExec( ) {

       
$argc = func_num_args();
       
$argv = func_get_args();

   
$cmd = '';
    for(
$i=0; $i<$argc ; $i++) {
        if(
$i != ($argc-1) ) {
         
$cmd .= $argv[$i]." && ";
        }else{
         
$cmd .= $argv[$i];
        }
    }
    echo
$cmd;

       
$stream = ssh2_exec( $this->con, $cmd );
   
stream_set_blocking( $stream, true );
    return
fread( $stream, 4096 );

  }

  function
getLog() {

     return
$this->log;

  }

}

?>
up
0
devoldemar
1 year ago
Usage of 'hostkey' option makes sence when you need to check authenticity of the remote server, e.g. by means of ssh2_fingerprint function. For that purpose you specify a list of possible algorithms sorted by priority in descending order. Supported values also include 'ssh-ed25519', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384' and 'ecdsa-sha2-nistp521'.
For instance:
<?php
$ssh
= ssh2_connect('192.168.3.1', 22, ['hostkey' => 'ssh-ed25519,ssh-rsa']);
$md5 = ssh2_fingerprint($ssh); // returns MD5 hash of ED25519 host key, or MD5 hash of RSA key if the key of previous type is absent
?>

Note, if the remote server does not have a key of appropriate type connection will fail:
<?php
$ssh
= ssh2_connect('192.168.3.1', 22, ['hostkey' => 'ssh-dss']);
PHP Warningssh2_connect(): Error starting up SSH connection(-5): Unable to exchange encryption keys in php shell code on line 1
PHP Warning
ssh2_connect(): Unable to connect to 192.168.3.1 in php shell code on line 1
?>
up
0
rainerkrauss at googlemail dot com
10 years ago
Warning! If you open a ssh connection and execute an external program opening another ssh connection it may result in very strange behavior.

I used an sftp connection to get a file list and used "exec" to download the files afterwards with an external sftp. lftp downloaded zeros with no comment, psftp exits with error code 11 most of the time, but sometimes it works - probably depending on how quickly php collects garbage and closes the unused connection first.

As there is no function to close a connection, you need to be sure to destroy all references (unset) to close it.
To Top