Подтвердить что ты не робот

Невозможно вызвать вызовы ssh2_connect()

Я использую метод ssh2_connect() для установления соединения с удаленным сервером. Соединение правильно устанавливается, если я предоставляю правильное имя хоста и номер порта. Когда я не могу подключиться из-за неправильных учетных данных, я пытаюсь вызвать функцию обратного вызова, но способ, которым я пытаюсь это сделать, не вызывает обратный вызов после сбоя подключения.

Это код, который я пробовал:

$callbacks = array( 
      'ignore' => array($this, 'callbackSshDisconnect'), 
      'debug' => array($this, 'callbackSshDisconnect'), 
      'macerror' => array($this, 'callbackSshDisconnect'), 
      'disconnect' => array($this, 'callbackSshDisconnect'), 
);

ssh2_connect($hostName,$port,array('hostkey', 'ssh-rsa'),$callbacks);

public function callbackSshDisconnect($reason, $message, $language) {
    $this->log('disconnected');
    $this->log($reason);die;
}

Что я делаю неправильно?

4b9b3361

Ответ 1

Нет ничего, что вы делаете неправильно, кроме опечатки: array('hostkey', 'ssh-rsa') должно быть array('hostkey' => 'ssh-rsa'). Функция ssh_connect() просто возвращает false для отказа соединения; обратные вызовы просто не инициируются, когда используются неправильные учетные данные.

Существуют решения (например, как предлагается rubo77 ниже), но тот, который я нахожу, даст вам наибольший контроль и позволит вам делать то, что вы хотите (например, отслеживать ошибки MAC), использовать библиотеку phpseclib (http://phpseclib.sourceforge.net/ssh/intro.html) для соединений ssh ​​и управления. Он обеспечивает очень точный контроль команд, а также включает в себя ведение журнала.

Это не самое простое решение, но вы можете управлять так же точно, как если бы вы были на клавиатуре/терминале напрямую.

У вас есть контроль над таймаутами и вы можете использовать обратный вызов для команд. Но если вам нужен лучший контроль, используйте read() и write(), и вы можете следить за отключением или другими проблемами. Проверьте документацию по протоколированию с помощью phpseclib: вы можете регистрировать и анализировать журнал или вызывать getLastError().

Журнальные файлы будут отображаться 'Connection closed by server' при отключении, например, но также сообщают вам, используете ли вы неподдерживаемый режим аутентификации при входе в систему и т.д.

Или для большего, прочитайте код: здесь, например, есть причины отключения:

    $this->disconnect_reasons = array(
        1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT',
        2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR',
        3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED',
        4 => 'NET_SSH2_DISCONNECT_RESERVED',
        5 => 'NET_SSH2_DISCONNECT_MAC_ERROR',
        6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR',
        7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE',
        8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED',
        9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE',
        10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST',
        11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION',
        12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS',
        13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER',
        14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE',
        15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'
    );

Ответ 2

Когда ssh2_connect терпит неудачу из-за неправильного хоста, порта и т.д., он не вызывает никаких обратных вызовов.

Вместо этого возвращается false

Документация PHP:
Возвращает ресурс с успехом или FALSE при ошибке.

$result = ssh2_connect($hostName,$port,array('hostkey' => 'ssh-rsa'),$callbacks);
if ($result === false)
   exit("ssh2_connect failed");

Кроме того, прочитав документ,

array('hostkey', 'ssh-rsa')

должен быть

array('hostkey' => 'ssh-rsa')

Ответ 3

Даже если вы будете использовать рабочий код, например:

$callbacks = array(
    'ignore' => 'callback',
    'debug' => 'callback',
    'macerror' => 'callback',
    'disconnect' =>'callback',
);

$session = ssh2_connect($hostName, $port, array('hostkey' => 'ssh-rsa'), $callbacks);
if($session === false) {
    print('Connection failed' . PHP_EOL);
    exit(1);
}

if(!ssh2_auth_pubkey_file(
    $session,
    "user",
    '/home/user/.ssh/id_rsa.pub',
    '/home/user/.ssh/id_rsa'
)) {
    print('Failed to authenticate session' . PHP_EOL);
    exit(2);
}

// Check this great answer:
// http://stackoverflow.com/a/12094837/171318
$stream = ssh2_exec($session, "ls -al");
stream_set_blocking($stream, true);
$stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
echo stream_get_contents($stream);  

function callback($reason, $message, $language) {
    print("callback:" . PHP_EOL);
    print(" " . $message . PHP_EOL);
    print(" " . $reason . PHP_EOL);
}

обратные вызовы не будут вызваны в обычном приложении. Это связано с тем, что они вызывались при определенных обстоятельствах, указанных на странице

Обратный вызов disconnect, например, вызывается только при получении пакета SSH2_MSG_DISCONNECT. Такой пакет не принимается, если сервер не закрывает соединение, которое обычно не будет выполняться.

Ответ 4

Если вы не можете подключиться из-за неправильных учетных данных, вы все равно не получите никаких обратных вызовов, ssh2_connect() просто возвращает false в этом случае.

Если вы действительно хотите поймать причину сбоя, вы можете использовать обработчик выходного буфера для извлечения сообщения об ошибке (при условии, что у вас установлен отчет об ошибках):

set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) {
    list($command,$errormessage)=explode(":",$errstr,2);
    echo "Error ($errno):", $errormessage."<br><br>";
});
$connection = ssh2_connect($hostName,$port);
restore_error_handler();