Paramiko SFTP 不会使用正确的用户名和密码进行身份验证,但 GUI SFTP 客户端会通过键盘交互式身份验证成功

Paramiko SFTP will not authenticate with correct username and password but GUI SFTP client success with keyboard-interactive authentication

我有一些 Python 代码可用于一台 SFTP 主机,但是当我将配置更改为另一台 SFTP 主机以及用户名和密码时,连接失败。您将不得不相信我主机、端口、用户名和密码是完全正确的,并且我可以从同一台 PC 上的 FileZilla 手动连接。

如果我在最后一行进行调试,我可以看到以下传输值:

<paramiko.Transport at 0x88f0b400 (cipher aes128-ctr, 128 bits) (connected; awaiting auth)>

当我 运行 完成时,它在最后一行以通用“EOFError”失败,这当然是因为我无法验证传输。

我做错了什么?

import configparser
import paramiko


def main():
    config = configparser.ConfigParser()
    config.read('pullICEHistory.ini')
    sftp_config = config['ICEFTPHost']
    host = sftp_config['host']
    port = int(sftp_config['port'])
    username = sftp_config['username']
    password = sftp_config['password']
    download_path = sftp_config['download_path']
    transport = paramiko.Transport((host, port))
    transport.connect(username=username, password=password, hostkey=None)
    sftp = paramiko.SFTPClient.from_transport(transport)


if __name__ == '__main__':
    main()

这是 Paramiko 日志:

DEB [20210813-08:50:54.497] thr=1   paramiko.transport: starting thread (client mode): 0x5c153df0
DEB [20210813-08:50:54.497] thr=1   paramiko.transport: Local version/idstring: SSH-2.0-paramiko_2.7.2
DEB [20210813-08:50:54.504] thr=1   paramiko.transport: Remote version/idstring: SSH-2.0-Server
INF [20210813-08:50:54.504] thr=1   paramiko.transport: Connected (version 2.0, client Server)
DEB [20210813-08:50:54.512] thr=1   paramiko.transport: kex algos:['ecdh-sha2-nistp521', 'ecdh-sha2-nistp384', 'ecdh-sha2-nistp256', 'diffie-hellman-group-exchange-sha256', 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group18-sha512', 'diffie-hellman-group17-sha512', 'diffie-hellman-group16-sha512', 'diffie-hellman-group15-sha512', 'diffie-hellman-group14-sha256', 'diffie-hellman-group14-sha1', 'diffie-hellman-group1-sha1'] server key:['ecdsa-sha2-nistp256', 'ssh-rsa'] client encrypt:['blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'arcfour256', 'arcfour128', 'aes128-cbc', '3des-cbc', 'aes192-cbc', 'aes256-cbc'] server encrypt:['blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'arcfour256', 'arcfour128', 'aes128-cbc', '3des-cbc', 'aes192-cbc', 'aes256-cbc'] client mac:['hmac-md5', 'hmac-sha1', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1-96', 'hmac-md5-96'] server mac:['hmac-md5', 'hmac-sha1', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1-96', 'hmac-md5-96'] client compress:['none'] server compress:['none'] client lang:[''] server lang:[''] kex follows?False
DEB [20210813-08:50:54.513] thr=1   paramiko.transport: Kex agreed: ecdh-sha2-nistp256
DEB [20210813-08:50:54.513] thr=1   paramiko.transport: HostKey agreed: ecdsa-sha2-nistp256
DEB [20210813-08:50:54.513] thr=1   paramiko.transport: Cipher agreed: aes128-ctr
DEB [20210813-08:50:54.513] thr=1   paramiko.transport: MAC agreed: hmac-sha2-256
DEB [20210813-08:50:54.513] thr=1   paramiko.transport: Compression agreed: none
DEB [20210813-08:50:54.523] thr=1   paramiko.transport: kex engine KexNistp256 specified hash_algo <built-in function openssl_sha256>
DEB [20210813-08:50:54.531] thr=1   paramiko.transport: Switch to new keys ...
DEB [20210813-08:50:54.531] thr=2   paramiko.transport: Attempting password auth...
DEB [20210813-08:50:54.539] thr=1   paramiko.transport: userauth is OK
INF [20210813-08:50:54.749] thr=1   paramiko.transport: Authentication continues...
DEB [20210813-08:50:54.749] thr=1   paramiko.transport: Methods: ['keyboard-interactive']
DEB [20210813-08:50:54.750] thr=2   paramiko.transport: [chan 0] Max packet in: 32768 bytes
DEB [20210813-08:50:54.758] thr=1   paramiko.transport: EOF in transport thread

这是来自 FileZilla 的详细日志,主机名和用户名已编辑:

Trace:  CControlSocket::SendNextCommand()
Trace:  CSftpConnectOpData::Send() in state 0
Status: Connecting to sftp.icedatavault.icedataservices.com...
Trace:  Going to execute C:\Program Files\FileZilla FTP Client\fzsftp.exe
Response:   fzSftp started, protocol_version=11
Trace:  CSftpConnectOpData::ParseResponse() in state 0
Trace:  CControlSocket::SendNextCommand()
Trace:  CSftpConnectOpData::Send() in state 3
Command:    open "***@***.com" 22
Trace:  Looking up host "sftp.***.com" for SSH connection
Trace:  Connecting to ***.***.***.*** port 22
Trace:  We claim version: SSH-2.0-FileZilla_3.55.0
Trace:  Connected to ***.***.***.***
Trace:  Remote version: SSH-2.0-Server
Trace:  Using SSH protocol version 2
Trace:  Doing ECDH key exchange with curve nistp256 and hash SHA-256 (unaccelerated)
Trace:  Server also has ssh-rsa host key, but we don't know it
Trace:  Host key fingerprint is:
Trace:  ecdsa-sha2-nistp256 256 SHA256:1ZH9bMfa6PSeIJBAvO4wg3SIiTizufzlB/z7b4qeQfA
Trace:  Initialised AES-256 SDCTR (AES-NI accelerated) outbound encryption
Trace:  Initialised HMAC-SHA-256 (unaccelerated) outbound MAC algorithm
Trace:  Initialised AES-256 SDCTR (AES-NI accelerated) inbound encryption
Trace:  Initialised HMAC-SHA-256 (unaccelerated) inbound MAC algorithm
Status: Using username "***". 
Trace:  Attempting keyboard-interactive authentication
Command:    Pass: ********
Trace:  Access granted
Trace:  Opening main session channel
Trace:  Opened main channel
Trace:  Started a shell/command
Status: Connected to sftp-consumer.***.com
Trace:  Remote working directory is /
Trace:  CSftpConnectOpData::ParseResponse() in state 3
Trace:  CControlSocket::ResetOperation(0)
Trace:  CSftpConnectOpData::Reset(0) in state 3
Trace:  CControlSocket::SendNextCommand()
Trace:  CSftpListOpData::Send() in state 0
Status: Retrieving directory listing...
Trace:  CSftpChangeDirOpData::Send() in state 0
Trace:  CSftpChangeDirOpData::Send() in state 1
Command:    pwd
Response:   Current directory is: "/"
Trace:  CSftpChangeDirOpData::ParseResponse() in state 1
Trace:  CControlSocket::ResetOperation(0)
Trace:  CSftpChangeDirOpData::Reset(0) in state 1
Trace:  CSftpListOpData::SubcommandResult(0) in state 1
Trace:  CControlSocket::SendNextCommand()
Trace:  CSftpListOpData::Send() in state 2
Trace:  CControlSocket::ResetOperation(0)
Trace:  CSftpListOpData::Reset(0) in state 2
Status: Directory listing of "/" successful

编辑:这是使用 SSHClient() 时的 Paramiko 日志:

DEB [20210813-10:48:43.523] thr=1   paramiko.transport: starting thread (client mode): 0x6917bd90
DEB [20210813-10:48:43.524] thr=1   paramiko.transport: Local version/idstring: SSH-2.0-paramiko_2.7.2
DEB [20210813-10:48:43.532] thr=1   paramiko.transport: Remote version/idstring: SSH-2.0-Server
INF [20210813-10:48:43.532] thr=1   paramiko.transport: Connected (version 2.0, client Server)
DEB [20210813-10:48:43.540] thr=1   paramiko.transport: kex algos:['ecdh-sha2-nistp521', 'ecdh-sha2-nistp384', 'ecdh-sha2-nistp256', 'diffie-hellman-group-exchange-sha256', 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group18-sha512', 'diffie-hellman-group17-sha512', 'diffie-hellman-group16-sha512', 'diffie-hellman-group15-sha512', 'diffie-hellman-group14-sha256', 'diffie-hellman-group14-sha1', 'diffie-hellman-group1-sha1'] server key:['ecdsa-sha2-nistp256', 'ssh-rsa'] client encrypt:['blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'arcfour256', 'arcfour128', 'aes128-cbc', '3des-cbc', 'aes192-cbc', 'aes256-cbc'] server encrypt:['blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'arcfour256', 'arcfour128', 'aes128-cbc', '3des-cbc', 'aes192-cbc', 'aes256-cbc'] client mac:['hmac-md5', 'hmac-sha1', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1-96', 'hmac-md5-96'] server mac:['hmac-md5', 'hmac-sha1', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1-96', 'hmac-md5-96'] client compress:['none'] server compress:['none'] client lang:[''] server lang:[''] kex follows?False
DEB [20210813-10:48:43.541] thr=1   paramiko.transport: Kex agreed: ecdh-sha2-nistp256
DEB [20210813-10:48:43.541] thr=1   paramiko.transport: HostKey agreed: ecdsa-sha2-nistp256
DEB [20210813-10:48:43.541] thr=1   paramiko.transport: Cipher agreed: aes128-ctr
DEB [20210813-10:48:43.541] thr=1   paramiko.transport: MAC agreed: hmac-sha2-256
DEB [20210813-10:48:43.541] thr=1   paramiko.transport: Compression agreed: none
DEB [20210813-10:48:43.554] thr=1   paramiko.transport: kex engine KexNistp256 specified hash_algo <built-in function openssl_sha256>
DEB [20210813-10:48:43.562] thr=1   paramiko.transport: Switch to new keys ...
DEB [20210813-10:48:43.563] thr=2   paramiko.transport: Adding ecdsa-sha2-nistp256 host key for sftp.icedatavault.icedataservices.com: b'a01d678327cf500d704d970aacf24049'
DEB [20210813-10:48:43.580] thr=1   paramiko.transport: userauth is OK
INF [20210813-10:48:43.926] thr=1   paramiko.transport: Authentication continues...
DEB [20210813-10:48:43.926] thr=1   paramiko.transport: Methods: ['keyboard-interactive']
DEB [20210813-10:48:43.937] thr=3   paramiko.transport: starting thread (client mode): 0x6917bd00
DEB [20210813-10:48:43.938] thr=3   paramiko.transport: Local version/idstring: SSH-2.0-paramiko_2.7.2
DEB [20210813-10:48:43.945] thr=3   paramiko.transport: Remote version/idstring: SSH-2.0-Server
INF [20210813-10:48:43.945] thr=3   paramiko.transport: Connected (version 2.0, client Server)
DEB [20210813-10:48:43.954] thr=3   paramiko.transport: kex algos:['ecdh-sha2-nistp521', 'ecdh-sha2-nistp384', 'ecdh-sha2-nistp256', 'diffie-hellman-group-exchange-sha256', 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group18-sha512', 'diffie-hellman-group17-sha512', 'diffie-hellman-group16-sha512', 'diffie-hellman-group15-sha512', 'diffie-hellman-group14-sha256', 'diffie-hellman-group14-sha1', 'diffie-hellman-group1-sha1'] server key:['ecdsa-sha2-nistp256', 'ssh-rsa'] client encrypt:['blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'arcfour256', 'arcfour128', 'aes128-cbc', '3des-cbc', 'aes192-cbc', 'aes256-cbc'] server encrypt:['blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'arcfour256', 'arcfour128', 'aes128-cbc', '3des-cbc', 'aes192-cbc', 'aes256-cbc'] client mac:['hmac-md5', 'hmac-sha1', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1-96', 'hmac-md5-96'] server mac:['hmac-md5', 'hmac-sha1', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1-96', 'hmac-md5-96'] client compress:['none'] server compress:['none'] client lang:[''] server lang:[''] kex follows?False
DEB [20210813-10:48:43.954] thr=3   paramiko.transport: Kex agreed: ecdh-sha2-nistp256
DEB [20210813-10:48:43.954] thr=3   paramiko.transport: HostKey agreed: ecdsa-sha2-nistp256
DEB [20210813-10:48:43.954] thr=3   paramiko.transport: Cipher agreed: aes128-ctr
DEB [20210813-10:48:43.954] thr=3   paramiko.transport: MAC agreed: hmac-sha2-256
DEB [20210813-10:48:43.954] thr=3   paramiko.transport: Compression agreed: none
DEB [20210813-10:48:43.965] thr=3   paramiko.transport: kex engine KexNistp256 specified hash_algo <built-in function openssl_sha256>
DEB [20210813-10:48:43.972] thr=3   paramiko.transport: Switch to new keys ...
DEB [20210813-10:48:43.972] thr=2   paramiko.transport: Attempting password auth...
DEB [20210813-10:48:43.981] thr=3   paramiko.transport: userauth is OK
INF [20210813-10:48:44.266] thr=3   paramiko.transport: Authentication continues...
DEB [20210813-10:48:44.266] thr=3   paramiko.transport: Methods: ['keyboard-interactive']
DEB [20210813-10:48:44.267] thr=2   paramiko.transport: [chan 0] Max packet in: 32768 bytes
DEB [20210813-10:48:44.275] thr=3   paramiko.transport: EOF in transport thread
DEB [20210813-10:48:44.277] thr=1   paramiko.transport: EOF in transport thread

您的服务器似乎只支持键盘交互身份验证。当您在 Python/Paramiko 代码中使用密码验证时。

尝试使用高级ParamikoAPI、SSHClient。它会自动使用您的密码进行键盘交互式身份验证。

ssh = paramiko.SSHClient()
ssh.connect(host, port=port, username=username, password=password)

此外,SSHClient 正确验证了您服务器的主机密钥,而低级 Transport API 则没有(这是一个安全漏洞)。


事实证明上述方法也不起作用,因为服务器行为异常。

此解决方法有效: