Paramiko随机出现Authentication Failed认证失败问题求助(用户名密码正确)
Paramiko随机出现Authentication Failed认证失败问题求助(用户名密码正确)
环境信息
- Paramiko版本: 2.7.2
- Python版本: 3.5.10
- 操作系统: Linux, CentOS Linux 7 (Core)
问题描述
我们用Python通过Paramiko连接SSH服务器时,随机出现"authentication failed"错误,但有时候又能正常连接。直接用命令行SSH连接服务器完全没问题,而且确认用户名、密码、主机名都是正确的。
运行场景
- 代码通过crontab以15分钟间隔定时执行
- 认证失败的情况是随机发生的
代码片段
import paramiko import traceback ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: ssh.connect(hostname, 22, username, password) ssh.close() except Exception as ssherror: traceback.print_exc()
错误回溯
Traceback (most recent call last): File "sshToServer.py", line 15, in getCPUCount ssh.connect(hostname, 22, username, password) File "/home/user/env/lib/python3.5/site-packages/paramiko/client.py", line 446, in connect passphrase, File "/home/user/env/lib/python3.5/site-packages/paramiko/client.py", line 764, in _auth raise saved_exception File "/home/user/env/lib/python3.5/site-packages/paramiko/client.py", line 751, in _auth self._transport.auth_password(username, password) File "/home/user/env/lib/python3.5/site-packages/paramiko/transport.py", line 1509, in auth_password return self.auth_handler.wait_for_response(my_event) File "/home/user/env/lib/python3.5/site-packages/paramiko/auth_handler.py", line 250, in wait_for_response raise e paramiko.ssh_exception.AuthenticationException: Authentication failed.
可能的原因及解决思路
1. SSH服务器的速率限制/防暴力破解机制
很多SSH服务器(比如OpenSSH)默认会对频繁的认证请求做速率限制,尤其是来自同一IP的重复尝试。你的脚本15分钟执行一次看起来不频繁,但如果服务器端的规则比较严格,或者同一时间段有其他设备也在连这个服务器,可能会触发临时的封禁/限制。
解决方法:
- 检查服务器端的
/var/log/secure日志(CentOS下),搜索对应客户端IP的认证记录,看是否有Failed password之外的提示(比如maximum authentication attempts exceeded或者too many failures) - 给脚本添加重试机制,遇到认证失败时短暂延迟后重试几次,示例代码:
import paramiko import traceback import time ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) max_retries = 3 retry_delay = 5 # 秒 success = False for attempt in range(max_retries): try: ssh.connect(hostname, 22, username, password, timeout=10) print("连接成功") ssh.close() success = True break except paramiko.ssh_exception.AuthenticationException as ae: if attempt < max_retries -1: print(f"认证失败,第{attempt+1}次重试...") time.sleep(retry_delay) else: traceback.print_exc() except Exception as ssherror: traceback.print_exc() break
2. Paramiko的认证顺序问题
Paramiko在_auth方法中会尝试多种认证方式(比如先尝试密钥认证,再尝试密码认证),如果服务器端的认证方式顺序和Paramiko不匹配,或者中间有超时,可能会导致密码认证被跳过或者失败。
解决方法:
在ssh.connect()中明确指定只使用密码认证,避免尝试其他不需要的认证方法:
ssh.connect(hostname, 22, username, password, look_for_keys=False, allow_agent=False)
look_for_keys=False:禁用尝试本地密钥文件认证allow_agent=False:禁用尝试SSH代理认证
3. 网络波动导致的认证数据包丢失
如果客户端和服务器之间的网络不稳定,认证过程中的数据包可能丢包,导致认证失败。这种情况的失败也是随机的。
解决方法:
- 在
connect()中添加timeout参数,避免长时间等待无响应:ssh.connect(hostname, 22, username, password, timeout=10)(单位:秒) - 结合前面的重试机制,遇到超时或认证失败时重试
4. 服务器端的PAM模块限制
CentOS的SSH可能使用PAM进行认证,PAM的某些规则(比如pam_tally2模块的失败次数限制)可能会临时锁定账号,导致随机认证失败。
解决方法:
- 服务器端执行
pam_tally2 --user 你的用户名,查看是否有失败次数累计导致的临时锁定 - 检查
/etc/pam.d/sshd配置,看是否有相关的限制规则,必要时调整
期望目标
希望能实现稳定连接SSH服务器,不再出现随机的认证失败问题。
备注:内容来源于stack exchange,提问作者Bonthu Srinivasa rao




