1、使用paramiko模块连接sftp报错:paramiko.ssh_exception.AuthenticationException: Authentication failed.
直接上代码:
def connect_with_private_key():
# SFTP连接参数
hostname = 'xxxxxxxxx'
port = 22
username = 'xxxx'
private_key_path = r".ssh\id_rsa" # 替换为您的私钥路径
# 加载私钥
private_key = paramiko.RSAKey.from_private_key_file(private_key_path)
# 创建SSH客户端
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 建立连接
ssh.connect(hostname=hostname, port=port, username=username, pkey=private_key)
# 创建SFTP客户端
sftp = ssh.open_sftp()
print("SFTP连接成功!")
# 示例: 列出根目录文件
print("根目录文件:", sftp.listdir('.'))
# 关闭连接
sftp.close()
ssh.close()
if __name__ == "__main__":
connect_with_private_key()
如果你确认了连接信息都是无误的情况下,还是报错了`Authentication failed`

那么接下来你需要使用第三方客户端连接sftp,我这边使用了MobaXterm软件连接是可以连接上的,那么我们可以肯定的是连接信息和防火墙都是不存在问题的,我们把范围缩小看看MobaXterm连接是不是做了什么操作?
我们可以问下大模型,把所有可能出现的情况都尝试一遍;最终确认了是服务端配置了特定的认证方法顺序

把完整的诊断代码贴上:
import paramiko
import logging
import os
# 配置详细日志
logging.basicConfig()
logging.getLogger("paramiko").setLevel(logging.DEBUG)
def diagnose_connection():
host = 'your_host'
port = 22
username = 'your_username'
key_path = '/path/to/private_key'
# 检查私钥权限
try:
st = os.stat(key_path)
if st.st_mode & 0o7777 != 0o600:
print(f"警告: 私钥权限应为 600,当前为 {oct(st.st_mode)[-3:]}")
print("尝试修复权限...")
os.chmod(key_path, 0o600)
except Exception as e:
print(f"权限检查错误: {e}")
# 创建 SSH 客户端
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 尝试加载私钥
key = None
key_types = [
('RSA', paramiko.RSAKey),
('Ed25519', paramiko.Ed25519Key),
('ECDSA', paramiko.ECDSAKey)
]
for name, key_class in key_types:
try:
key = key_class.from_private_key_file(key_path)
print(f"成功加载 {name} 密钥")
break
except paramiko.ssh_exception.PasswordRequiredException:
print(f"{name} 密钥需要密码")
try:
key = key_class.from_private_key_file(key_path, password='your_passphrase')
print(f"使用密码成功加载 {name} 密钥")
break
except:
continue
except:
continue
if not key:
print("无法加载任何类型的密钥")
return
# 尝试连接
try:
client.connect(
hostname=host,
port=port,
username=username,
pkey=key,
timeout=10,
allow_agent=False,
look_for_keys=False,
disabled_algorithms={'pubkeys': ['rsa-sha2-256', 'rsa-sha2-512']}
)
print("连接成功!")
# 测试 SFTP
sftp = client.open_sftp()
files = sftp.listdir()
print(f"找到 {len(files)} 个文件")
sftp.close()
except paramiko.AuthenticationException as e:
print(f"认证失败: {e}")
print("可能原因:")
print("1. 用户名错误")
print("2. 私钥不匹配")
print("3. 服务器不接受此密钥类型")
except paramiko.SSHException as e:
print(f"SSH 错误: {e}")
except Exception as e:
print(f"其他错误: {e}")
finally:
client.close()
# 运行诊断
diagnose_connection()
最终我们连接上了!
知识点:
Paramiko 连接参数详解:allow_agent, look_for_keys 和 disabled_algorithms
这三个参数在 Paramiko 的 connect() 方法中用于控制 SSH 连接的行为,特别是身份验证过程和算法协商。下面我将详细解释每个参数的作用、使用场景和实际影响。
1.1 allow_agent=False
作用
- 禁用 SSH 代理支持:阻止 Paramiko 尝试使用本地 SSH 代理(如 ssh-agent 或 Pageant)进行身份验证
- 防止自动使用代理中的密钥:即使系统中有活动的 SSH 代理,也不会使用其中的密钥
使用场景
- 当你想显式控制身份验证凭据,避免使用系统缓存的密钥
- 在安全敏感环境中,避免意外使用代理中的密钥
- 当调试身份验证问题时,排除代理干扰
- 在容器化环境中,可能没有 SSH 代理可用
默认行为
- 如果未指定,默认为
True,Paramiko 会尝试使用 SSH 代理
示例
# 显式禁用 SSH 代理
client.connect(
hostname='example.com',
username='user',
password='pass',
allow_agent=False # 不使用任何 SSH 代理
)
1.2 look_for_keys=False
作用
- 禁用本地密钥查找:阻止 Paramiko 在用户主目录的
.ssh文件夹中查找私钥文件 - 避免自动尝试密钥认证:即使没有提供密钥,也不会尝试使用默认位置的密钥
使用场景
- 当你想仅使用密码认证时
- 当显式提供密钥文件时,避免额外的密钥查找
- 在安全加固环境中,防止意外使用默认密钥
- 当连接速度很重要时,减少不必要的密钥查找时间
默认行为
- 如果未指定,默认为
True,Paramiko 会尝试在以下位置查找密钥:~/.ssh/id_rsa~/.ssh/id_dsa~/.ssh/id_ecdsa~/.ssh/id_ed25519
示例
# 禁用本地密钥查找
client.connect(
hostname='example.com',
username='user',
password='pass',
look_for_keys=False # 不查找 ~/.ssh 中的密钥
)
1.3 disabled_algorithms={'pubkeys': ['rsa-sha2-256', 'rsa-sha2-512']}
作用
- 禁用特定公钥算法:明确禁止使用指定的公钥签名算法
- 解决算法兼容性问题:当客户端和服务器支持的算法不匹配时
参数结构
- 接受一个字典,其中键指定算法类别,值是该类别中要禁用的算法列表
- 本例中禁用了两种公钥算法:
rsa-sha2-256:使用 SHA-256 哈希的 RSA 签名rsa-sha2-512:使用 SHA-512 哈希的 RSA 签名
使用场景
- 连接旧版 SSH 服务器(如 OpenSSH 7.2 之前版本),这些服务器不支持新的 RSA-SHA2 签名方案
- 解决错误:"
no matching host key type" 或 "sign_and_send_pubkey: no mutual signature algorithm" - 当服务器配置错误或使用自定义 SSH 实现时
- 安全策略要求禁用特定算法
示例
# 禁用特定的公钥算法
client.connect(
hostname='old-server.example.com',
username='user',
key_filename='id_rsa',
disabled_algorithms={'pubkeys': ['rsa-sha2-256', 'rsa-sha2-512']}
)
三个参数组合使用的场景
当这三个参数一起使用时,通常是为了严格控制身份验证过程:
client.connect(
hostname='legacy-server.example.com',
port=22,
username='admin',
pkey=private_key, # 显式提供密钥对象
allow_agent=False, # 不使用 SSH 代理
look_for_keys=False, # 不在本地查找密钥
disabled_algorithms={'pubkeys': ['rsa-sha2-256', 'rsa-sha2-512']} # 禁用新算法
)
这种组合的典型场景:
- 连接旧系统:连接到不支持新 RSA-SHA2 算法的旧 SSH 服务器
- 安全敏感环境:精确控制使用的凭据和算法
- 自动化脚本:确保一致的行为,不受本地环境的影响
- 调试环境:排除代理和自动密钥查找的干扰
参数间的相互作用
| 参数 | 影响 allow_agent | 影响 look_for_keys | 影响 disabled_algorithms |
|---|---|---|---|
| 身份验证源 | 控制代理使用 | 控制本地密钥查找 | 不影响身份验证源 |
| 算法选择 | 不影响 | 不影响 | 限制可用算法 |
| 连接速度 | 减少代理查询时间 | 减少密钥查找时间 | 可能减少算法协商时间 |
| 安全性 | 防止意外使用代理密钥 | 防止意外使用默认密钥 | 可能降低安全性(禁用新算法) |
1146

被折叠的 条评论
为什么被折叠?



