带有 SFTP 的 Paramiko SSH 客户端

Posted

技术标签:

【中文标题】带有 SFTP 的 Paramiko SSH 客户端【英文标题】:Paramiko's SSHClient with SFTP 【发布时间】:2011-04-07 19:12:56 【问题描述】:

如何通过远程服务器上的SSHClient 进行 SFTP 传输?我有一个本地主机和两个远程主机。远程主机是备份服务器和 Web 服务器。我需要在备份服务器上找到必要的备份文件并通过 SFTP 将其放在 Web 服务器上。如何使 Paramiko 的 SFTP 传输与 Paramiko 的 SSHClient 一起工作?

【问题讨论】:

【参考方案1】:

接受的答案“有效”。但是由于它使用了低级的Transport 类,它绕过了主机密钥验证,这是一个安全漏洞,因为它使代码容易受到Man-in-the-middle attacks 的影响。

最好使用正确的 Paramiko SSH API,SSHClient,它会验证主机密钥:

import paramiko
paramiko.util.log_to_file("paramiko.log")

ssh = paramiko.SSHClient()
ssh.connect(host, username='user', password='password')
# or 
# key = paramiko.RSAKey.from_private_key_file('id_rsa')
# ssh.connect(host, username='user', pkey=key)

sftp = ssh.open_sftp()

sftp.get(remotepath, localpath)
# or
sftp.put(localpath, remotepath2)

有关验证主机密钥的详细信息,请参阅:Paramiko "Unknown Server"

【讨论】:

【参考方案2】:

除了第一个很好但取决于用户名/密码的答案之外,以下显示了如何使用 ssh 密钥:

from paramiko import Transport, SFTPClient, RSAKey
key = RSAKey(filename='path_to_my_rsakey')
con = Transport('remote_host_name_or_ip', 22)
con.connect(None,username='my_username', pkey=key)
sftp = SFTPClient.from_transport(con)
sftp.listdir(path='.')

【讨论】:

【参考方案3】:

如果你有SSHClient,也可以使用open_sftp()

import paramiko


# lets say you have SSH client...
client = paramiko.SSHClient()

sftp = client.open_sftp()

# then you can use upload & download as shown above
...

【讨论】:

首先,这不是一个独立的答案,而仅仅是对@leoluk 答案的评论。其次,如果你有SSHClient,你可以简单地做sftp = client.open_sftp()【参考方案4】:

paramiko.SFTPClient

示例用法:

import paramiko
paramiko.util.log_to_file("paramiko.log")

# Open a transport
host,port = "example.com",22
transport = paramiko.Transport((host,port))

# Auth    
username,password = "bar","foo"
transport.connect(None,username,password)

# Go!    
sftp = paramiko.SFTPClient.from_transport(transport)

# Download
filepath = "/etc/passwd"
localpath = "/home/remotepasswd"
sftp.get(filepath,localpath)

# Upload
filepath = "/home/foo.jpg"
localpath = "/home/pony.jpg"
sftp.put(localpath,filepath)

# Close
if sftp: sftp.close()
if transport: transport.close()

【讨论】:

很好的答案。但是我要补充一点,TransportSFTPClient 都实现了 __enter__/__exit__ 接口,因此可以在上下文管理器中使用,例如with Transport((host, port)) as transport: 此实现有效,但它不清理进程。 sftp-server 进程与它分叉,如果你多次运行它,你可以看到代码完成后存在很多进程。 虽然这个工作,它使用低级Transport 类,它绕过主机密钥验证,这是一个安全漏洞,因为它使代码易受Man-in-the-middle attacks 的影响。更好的是使用正确的 Paramiko SSH API,SSHClient。见my answer。

以上是关于带有 SFTP 的 Paramiko SSH 客户端的主要内容,如果未能解决你的问题,请参考以下文章

使用 paramiko 防止 SFTP/SSH 会话超时

paramiko 实现ssh登录和sftp登录

Python学习—paramiko模块实现简单的ssh与sftp

python paramiko模块sftp异常:paramiko.ssh_exception.SSHException: EOF during negotiation

端口转发和使用 Python Paramiko 的开放式 SFTP

Python中SSH协议的实现 - Paramiko