Paramiko 是一个用 Python 编写的 SSHv2 协议实现库,用于安全地进行远程连接、执行命令、传输文件(SFTP)等操作

Paramiko 是一个用 Python 编写的 SSHv2 协议实现库,用于安全地进行远程连接、执行命令、传输文件(SFTP)等操作
Paramiko 是一个用 Python 编写的 SSHv2 协议实现库用于安全地进行远程连接、执行命令、传输文件SFTP等操作。它不依赖外部 SSH 二进制程序如 OpenSSH纯 Python 实现跨平台兼容性好广泛应用于自动化运维、网络设备管理、CI/CD 脚本等场景。核心功能包括建立 SSH 连接支持密码、私钥、密钥口令等多种认证方式执行远程 Shell 命令并获取标准输出/错误使用 SFTP 子系统上传/下载文件、管理远程目录支持通道Channel复用、会话保持、超时与异常处理基础示例密码登录执行命令importparamiko clientparamiko.SSHClient()client.set_missing_host_key_policy(paramiko.AutoAddPolicy())# 自动接受未知主机密钥生产环境应校验try:client.connect(hostname192.168.1.100,usernameuser,passwordpass,timeout10)stdin,stdout,stderrclient.exec_command(uptime)print(stdout.read().decode())finally:client.close()使用私钥登录示例private_keyparamiko.RSAKey.from_private_key_file(/path/to/id_rsa,passwordkey_pass)# 若私钥有密码client.connect(hostname192.168.1.100,usernameuser,pkeyprivate_key)SFTP 文件上传示例sftpclient.open_sftp()sftp.put(local.txt,/remote/local.txt)sftp.close()⚠️ 安全提示生产环境中避免AutoAddPolicy()应使用RejectPolicy()并预置可信 host key敏感凭证密码、私钥建议通过环境变量或密钥管理服务加载始终显式关闭连接close()或使用with上下文管理器需封装适配。在 Paramiko 中安全验证远程服务器的 SSH 主机密钥是防范中间人攻击MITM的核心措施。绝不能使用AutoAddPolicy()生产环境而应显式校验主机密钥是否可信。以下是推荐的安全实践✅ 正确做法使用paramiko.MissingHostKeyPolicy的子类或预置已知主机密钥方案一基于已知 hosts 文件推荐类 OpenSSH 行为importparamiko# 加载已知主机密钥类似 ~/.ssh/known_hostshost_keysparamiko.HostKeys()host_keys.load(/path/to/known_hosts)# 可为 OpenSSH 格式文件clientparamiko.SSHClient()client.set_missing_host_key_policy(paramiko.RejectPolicy())# 拒绝未知主机client.set_host_keys(host_keys)try:client.connect(hostname192.168.1.100,usernameuser,key_filename/id_rsa)print(✅ 连接成功主机密钥已验证)exceptparamiko.BadHostKeyExceptionase:print(f❌ 主机密钥不匹配{e})exceptparamiko.AuthenticationException:print(❌ 认证失败)exceptExceptionase:print(f❌ 连接异常{e})finally:client.close()方案二首次连接时手动确认并持久化交互式安全初始化defconnect_with_manual_verification(hostname,username,**kwargs):clientparamiko.SSHClient()client.set_missing_host_key_policy(paramiko.RejectPolicy())try:client.connect(hostname,username,**kwargs)returnclientexceptparamiko.SSHExceptionase:ifNo hostkey for serverinstr(e)orisinstance(e,paramiko.BadHostKeyException):# 获取远程主机密钥不验证时临时连接transportparamiko.Transport((hostname,22))transport.start_client()remote_keytransport.get_remote_server_key()fingerprintremote_key.get_fingerprint().hex()# SHA256 hexParamiko ≥ 2.10print(f⚠️ 首次连接{hostname}密钥指纹{fingerprint})confirminput(是否信任该密钥(y/N): ).strip().lower()ifconfirmy:# 手动添加到 known_hostshost_keysparamiko.HostKeys()host_keys.add(hostname,remote_key.get_name(),remote_key)host_keys.save(/path/to/known_hosts)transport.close()returnconnect_with_manual_verification(hostname,username,**kwargs)else:raiseRuntimeError(用户拒绝信任主机密钥)raisee方案三硬编码可信公钥适用于固定、受控环境expected_keyparamiko.RSAKey(databytes.fromhex(...))# 从已验证的服务器导出的公钥 hexclientparamiko.SSHClient()client.set_missing_host_key_policy(paramiko.RejectPolicy())try:client.connect(hostname192.168.1.100,usernameuser,pkeyprivate_key)# 手动校验transportclient.get_transport()remote_keytransport.get_remote_server_key()ifremote_key.asbytes()!expected_key.asbytes():raiseValueError(❌ 主机密钥与预期不符)exceptExceptionase:print(e) 补充建议使用transport.get_remote_server_key().get_name()获取密钥类型ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519Paramiko ≥ 2.10 默认使用 SHA256 指纹旧版本用.get_fingerprint()返回 MD5不安全已弃用可结合ssh-keyscan提前批量获取可信密钥ssh-keyscan -t rsa,ecdsa,ed25519 host known_hosts✅ 总结安全 拒绝未知 显式信任 持久化验证而非自动接受。