SSHv2公钥认证示例-Paramiko复用 Transport 连接
在 Paramiko 中复用 Transport
连接时,若要通过 公钥认证(而非密码)建立连接,需手动加载私钥并与 Transport
关联。以下是详细操作步骤及完整代码示例:
步骤 1:加载私钥文件
使用 RSAKey
或 Ed25519Key
类加载本地私钥文件:
from paramiko import Transport, RSAKey# 加载私钥(支持加密的私钥)
private_key = RSAKey.from_private_key_file(filename='/path/to/private_key.pem', # 私钥路径password='your_key_password' # 若私钥有密码保护
)
步骤 2:创建 Transport 并连接
通过公钥认证建立连接,并复用该 Transport
:
# 创建 Transport 对象
transport = Transport(('hostname', 22))# 通过公钥认证连接
transport.connect(username='your_username', pkey=private_key # 关键:传递私钥对象
)
步骤 3:复用 Transport 执行操作
复用已连接的 Transport
创建 SSHClient
或直接操作通道:
# 方法 1:绑定到 SSHClient
from paramiko import SSHClientssh = SSHClient()
ssh._transport = transport # 复用 Transport
stdin, stdout, stderr = ssh.exec_command('ls -l')
print(stdout.read().decode())# 方法 2:直接操作通道
channel = transport.open_session()
channel.exec_command('df -h')
output = channel.recv(1024).decode()
print(output)
channel.close()
步骤 4:复用 Transport 创建 SFTP
from paramiko import SFTPClientsftp = SFTPClient.from_transport(transport) # 复用 Transport
sftp.put('local_file.txt', 'remote_file.txt')
sftp.close()
完整代码示例
import paramiko
from paramiko import Transport, RSAKey, SSHClient, SFTPClient# 1. 加载私钥
private_key = RSAKey.from_private_key_file(filename='~/.ssh/id_rsa',password='key_password' # 若无密码可省略
)# 2. 创建 Transport 并连接
transport = Transport(('your_host', 22))
transport.connect(username='your_user', pkey=private_key)try:# 3. 复用 Transport 执行命令ssh = SSHClient()ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('ls -l /tmp')print(stdout.read().decode())# 4. 复用 Transport 传输文件sftp = SFTPClient.from_transport(transport)sftp.put('localfile.txt', 'remotefile.txt')sftp.close()finally:# 5. 关闭 Transport(释放连接)transport.close()
关键注意事项
-
私钥权限
- 确保私钥文件权限为
600
:chmod 600 ~/.ssh/id_rsa
- 否则 Paramiko 会抛出
SSHException: Private key file is accessible to others
。
- 确保私钥文件权限为
-
主机密钥验证
生产环境中应避免使用AutoAddPolicy
,推荐提前将服务端公钥指纹加入known_hosts
:ssh = SSHClient() ssh.load_system_host_keys() # 加载系统已知主机密钥 ssh.connect(...) # 自动校验主机密钥
-
异常处理
添加对认证失败、连接超时的捕获:try:transport.connect(...) except paramiko.AuthenticationException:print("公钥认证失败!") except paramiko.SSHException as e:print(f"SSH 错误: {e}")
复用连接的优势
- 性能提升:避免重复的 TCP 连接和密钥交换开销。
- 资源节省:在高频操作(如批量文件传输)中减少系统资源消耗。
- 功能整合:同一连接支持混合操作(如命令执行 + SFTP 传输)。