You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Paramiko SSHClient连接SFTP服务器认证失败问题求助

Paramiko SSHClient认证失败排查方案

问题描述

使用相同凭据,WinSCP、pysftp以及直接使用Paramiko Transport均可正常连接SFTP服务器,但使用Paramiko SSHClient却抛出认证失败错误:

paramiko.ssh_exception.AuthenticationException: Authentication failed.

且完全相同的代码在同事环境中可正常运行。

代码示例

import pysftp
from base64 import decodebytes
import paramiko

username = "my_username"
password = "my_secret_password"
hostname = "ftp.hostname.tld"
directory = "/protected/directory"
port = 22
keydata = b"""AAAAB...TuQ=="""
key = paramiko.RSAKey(data=decodebytes(keydata))

# PYSFTP 可以正常工作!
cnopts = pysftp.CnOpts()
cnopts.hostkeys.add(hostname, 'ssh-rsa', key)
with pysftp.Connection(host=hostname, username=username, password=password, cnopts=cnopts) as sftp:
    files = sftp.listdir_attr(directory)
    test = "test"

# 直接用Paramiko Transport也可以正常工作!
with paramiko.Transport((hostname,port)) as transport:
    transport.connect(
        hostkey=key,
        username=username,
        password=password
    )
    with paramiko.SFTPClient.from_transport(transport) as sftp:
        files = sftp.listdir_attr(directory)
        test = "test"

# 用SSHClient建立连接的版本无法工作
ssh_client = paramiko.SSHClient()
ssh_client.get_host_keys().add(hostname=hostname, keytype="ssh-rsa", key=key)
ssh_client.connect(
    hostname=hostname, 
    username=username,
    password=password,
    port=port
)
sftp = ssh_client.open_sftp()
files = sftp.listdir_attr(directory)
test = "test"

失败会话的Paramiko日志

DEBUG:paramiko.transport:starting thread (client mode): 0x5dad0e50
DEBUG:paramiko.transport:Local version/idstring: SSH-2.0-paramiko_3.1.0
DEBUG:paramiko.transport:Remote version/idstring: SSH-2.0-srtSSHServer_11.00
INFO:paramiko.transport:Connected (version 2.0, client srtSSHServer_11.00)
DEBUG:paramiko.transport:=== Key exchange possibilities ===
DEBUG:paramiko.transport:kex algos: diffie-hellman-group14-sha256, diffie-hellman-group-exchange-sha256, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, diffie-hellman-group1-sha1, diffie-hellman-group-exchange-sha512@ssh.com
DEBUG:paramiko.transport:server key: ssh-rsa
DEBUG:paramiko.transport:client encrypt: aes256-ctr, aes128-ctr, aes256-cbc, twofish256-cbc, aes128-cbc, twofish256-ctr, aes192-ctr, twofish192-ctr, twofish128-ctr, twofish128-cbc
DEBUG:paramiko.transport:server encrypt: aes256-ctr, aes128-ctr, aes256-cbc, twofish256-cbc, aes128-cbc, twofish256-ctr, aes192-ctr, twofish192-ctr, twofish128-ctr, twofish128-cbc
DEBUG:paramiko.transport:client mac: hmac-sha3-512, hmac-sha3-384, hmac-sha3-256, hmac-sha3-224, hmac-sha2-512, hmac-sha2-384, hmac-sha2-256, hmac-sha2-224, hmac-sha1
DEBUG:paramiko.transport:server mac: hmac-sha3-512, hmac-sha3-384, hmac-sha3-256, hmac-sha3-224, hmac-sha2-512, hmac-sha2-384, hmac-sha2-256, hmac-sha2-224, hmac-sha1
DEBUG:paramiko.transport:client compress: none
DEBUG:paramiko.transport:server compress: none
DEBUG:paramiko.transport:client lang: <none>
DEBUG:paramiko.transport:server lang: <none>
DEBUG:paramiko.transport:kex follows: False
DEBUG:paramiko.transport:=== Key exchange agreements ===
DEBUG:paramiko.transport:Kex: diffie-hellman-group-exchange-sha256
DEBUG:paramiko.transport:HostKey: ssh-rsa
DEBUG:paramiko.transport:Cipher: aes128-ctr
DEBUG:paramiko.transport:MAC: hmac-sha2-256
DEBUG:paramiko.transport:Compression: none
DEBUG:paramiko.transport:=== End of kex handshake ===
DEBUG:paramiko.transport:Got server p (2048 bits)
DEBUG:paramiko.transport:kex engine KexGexSHA256 specified hash_algo <built-in function openssl_sha256>
DEBUG:paramiko.transport:Switch to new keys ...
DEBUG:paramiko.transport:Trying discovered key b'f28c2e56806b573d7fc45b9722242e5b' in C:\Users\my-user/.ssh/id_rsa
DEBUG:paramiko.transport:userauth is OK
DEBUG:paramiko.transport:Finalizing pubkey algorithm for key of type 'ssh-rsa'
DEBUG:paramiko.transport:Our pubkey algorithm list: ['rsa-sha2-512', 'rsa-sha2-256', 'ssh-rsa']
DEBUG:paramiko.transport:Server did not send a server-sig-algs list; defaulting to our first preferred algo ('rsa-sha2-512')
DEBUG:paramiko.transport:NOTE: you may use the 'disabled_algorithms' SSHClient/Transport init kwarg to disable that or other algorithms if your server does not support them!
INFO:paramiko.transport:Authentication (publickey) failed.
INFO:paramiko.transport:Disconnect (code 2): unexpected service request

排查方向

从日志和代码差异来看,重点检查以下几点:

  • 强制指定认证方式:SSHClient默认优先尝试本地公钥认证(日志显示它在尝试C:\Users\my-user/.ssh/id_rsa),而其他连接方式仅用密码认证。在connect方法中添加look_for_keys=False和allow_agent=False,强制只使用密码认证:

    ssh_client.connect(
        hostname=hostname, 
        username=username,
        password=password,
        port=port,
        look_for_keys=False,
        allow_agent=False
    )
    
  • 禁用不兼容的公钥签名算法:日志提示服务器不支持rsa-sha2-512算法,而SSHClient默认优先使用该算法。初始化SSHClient时禁用该算法:

    ssh_client = paramiko.SSHClient()
    ssh_client.disabled_algorithms = {'pubkeys': ['rsa-sha2-512']}
    ssh_client.get_host_keys().add(hostname=hostname, keytype="ssh-rsa", key=key)
    ssh_client.connect(...)
    
  • 检查本地SSH配置冲突:你的环境可能存在全局SSH配置(如C:\Users\my-user/.ssh/config)影响SSHClient行为,而同事环境无此配置。临时重命名.ssh目录后再测试连接。

  • 对比Paramiko版本:不同版本的Paramiko可能存在兼容性差异,执行pip show paramiko查看本地版本,切换到和同事相同的版本测试。

  • 排查代理或环境变量差异:你的环境可能运行了SSH代理(如Pageant),导致SSHClient尝试使用代理中的密钥认证。添加allow_agent=False可避免此问题。


内容的提问来源于stack exchange,提问作者jakobdo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 04:12:05