ParallelSSH - 使用 pssh2_client 时出现 SessionHandshakeError

ParallelSSH - SessionHandshakeError when using pssh2_client

使用 my_pkey.pubparallel-ssh module I'm trying to run SSH commands using Natinve Client but getting SessionHandshakeError. And if I use Paramiko Client instead, everything works fine. I met the requirementmy_pkey 在同一目录中。

这是我使用 Native Client 的代码(将真实 IP 更改为 'ip1''ip2'):

from pssh.pssh2_client import ParallelSSHClient

pkey = os.path.dirname(os.path.abspath(__file__)) + '/my_pkey'
hosts = ['ip1', 'ip2']
client = ParallelSSHClient(hosts, user='root', pkey=pkey)
output = client.run_command('hostname')
for host, host_output in output.items():
    for line in host_output.stdout:
        print(line)

出现此错误:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\ssh2_client.py", line 123, in _init
    self.session.handshake(self.sock)
  File "ssh2\session.pyx", line 81, in ssh2.session.Session.handshake
ssh2.exceptions.SessionHandshakeError: ('SSH session handshake failed with error code %s', -5)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\ssh2_client.py", line 123, in _init
    self.session.handshake(self.sock)
  File "ssh2\session.pyx", line 81, in ssh2.session.Session.handshake
ssh2.exceptions.SessionHandshakeError: ('SSH session handshake failed with error code %s', -5)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\ssh2_client.py", line 123, in _init
    self.session.handshake(self.sock)
  File "ssh2\session.pyx", line 81, in ssh2.session.Session.handshake
ssh2.exceptions.SessionHandshakeError: ('SSH session handshake failed with error code %s', -5)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:/Users/NazimokPP/Desktop/AnchorFree/QA-Automation/nodetest/nodetest.py", line 57, in <module>
    main(args.server_domain, args.test_type)
  File "C:/Users/NazimokPP/Desktop/AnchorFree/QA-Automation/nodetest/nodetest.py", line 45, in main
    output = client.run_command('hostname')
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\pssh2_client.py", line 182, in run_command
    encoding=encoding, use_pty=use_pty, timeout=timeout)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\base_pssh.py", line 91, in run_command
    self.get_output(cmd, output)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\base_pssh.py", line 136, in get_output
    (channel, host, stdout, stderr, stdin) = cmd.get()
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\greenlet.py", line 482, in get
    self._raise_exception()
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\greenlet.py", line 159, in _raise_exception
    reraise(*self.exc_info)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\_compat.py", line 33, in reraise
    raise value.with_traceback(tb)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\greenlet.py", line 536, in run
    result = self._run(*self.args, **self.kwargs)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\pssh2_client.py", line 188, in _run_command
    self._make_ssh_client(host)
File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\pssh2_client.py", line 313, in _make_ssh_client
    allow_agent=self.allow_agent, retry_delay=self.retry_delay)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\ssh2_client.py", line 107, in __init__
    THREAD_POOL.apply(self._init)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\pool.py", line 325, in apply
    return self.spawn(func, *args, **kwds).get()
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\event.py", line 385, in get
    return self.get(block=False)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\event.py", line 375, in get
    return self._raise_exception()
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\event.py", line 355, in _raise_exception
    reraise(*self.exc_info)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\_compat.py", line 33, in reraise
    raise value.with_traceback(tb)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\gevent\threadpool.py", line 211, in _worker
    value = func(*args, **kwargs)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\ssh2_client.py", line 126, in _init
    return self._connect_init_retry(retries)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\ssh2_client.py", line 116, in _connect_init_retry
    return self._init(retries=retries)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\ssh2_client.py", line 126, in _init
    return self._connect_init_retry(retries)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\ssh2_client.py", line 116, in _connect_init_retry
    return self._init(retries=retries)
  File "C:\Program Files (x86)\Python36-32\lib\site-packages\pssh\ssh2_client.py", line 128, in _init
    raise SessionError(msg, self.host, self.port, ex)
pssh.exceptions.SessionError: ('Error connecting to host %s:%s - %s', 'ip1', 22, SessionHandshakeError('SSH session handshake failed with error code %s', -5))

Process finished with exit code 1

这是我使用 Paramiko 客户端的代码(将真实 IP 更改为 'ip1' 和 'ip2'):

from pssh.pssh_client import ParallelSSHClient
from pssh.utils import load_private_key

key_path = os.path.dirname(os.path.abspath(__file__)) + '/my_pkey'
pkey = load_private_key(key_path)
hosts = ['ip1', 'ip2']
client = ParallelSSHClient(hosts, user='root', pkey=pkey)
output = client.run_command('hostname')
for host, host_output in output.items():
    for line in host_output.stdout:
        print(line)

并且有效。这是输出(我应该关心警告吗?):

C:\Program Files (x86)\Python36-32\lib\site-packages\paramiko\ecdsakey.py:202: CryptographyDeprecationWarning: signer and verifier have been deprecated. Please use sign and verify instead.
  signature, ec.ECDSA(self.ecdsa_curve.hash_object())
C:\Program Files (x86)\Python36-32\lib\site-packages\paramiko\rsakey.py:110: CryptographyDeprecationWarning: signer and verifier have been deprecated. Please use sign and verify instead.
  algorithm=hashes.SHA1(),
ip1.hostname
ip2.hostname

Process finished with exit code 0

我在 Native Client 上做错了什么?

我在 Google 组线程中从 Panos 那里得到的一些解释。它对我没有帮助,但也许对其他人有帮助。

A -5 error is defined as a key exchange error in libssh2. It sounds like the key type is not supported by libssh2 and paramiko shows 'ecdsakey.py' being used. ECDSA keys are not currently supported by libssh2 (PR pending).

The warning are from paramiko itself, can't say if they matter.

Better exceptions for native client errors are being worked on for next release.

_

So for a private key 'my_pkey', there should be a 'my_pkey.pub' in same directory.

It may also be a case of the SSH server's key not being supported by the native client (same limitations as user keys) which would explain the key exchange error. Can check the type of key configured for the server in /etc/ssh/sshd_config, HostKey entry. There should be at least one non-ECDSA key configured, eg:

HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key HostKey /etc/ssh/ssh_host_ecdsa_key

If there is only a ECDSA key entry, the native client will not be able to connect.

此错误被追踪到用于 Windows 上的 libssh2 的 WinCNG 后端 - 它不支持 SHA-256 主机密钥散列,这是 OpenSSH 最新版本中的默认设置服务器。

parallel-ssh1.6.0latest version 通过将 Windows 后端切换到 OpenSSL 来解决此问题,以获得更好的兼容性并匹配 OSX和Linux二进制轮。

有关详细信息,请参阅 release notes