12

因此,我正在尝试连接到 FTP 服务器以获取目录列表并下载文件。但是prot_p()函数之后的第一个命令引发异常 - 从日志中产生这些错误:

*get* '150 Here comes the directory listing.\r\n'
*resp* '150 Here comes the directory listing.'
*get* '522 SSL connection failed; session reuse required: see require_ssl_reuse
option in vsftpd.conf man page\r\n'
*resp* '522 SSL connection failed; session reuse required: see require_ssl_reuse
 option in vsftpd.conf man page'
Traceback (most recent call last):
  File "C:\temp\download.py", line 29, in <module>
    files = ftps.dir()
  File "C:\Python27\lib\ftplib.py", line 522, in dir
    self.retrlines(cmd, func)
  File "C:\Python27\lib\ftplib.py", line 725, in retrlines
    return self.voidresp()
  File "C:\Python27\lib\ftplib.py", line 224, in voidresp
    resp = self.getresp()
  File "C:\Python27\lib\ftplib.py", line 219, in getresp
    raise error_perm, resp
ftplib.error_perm: 522 SSL connection failed; session reuse required: see requir
e_ssl_reuse option in vsftpd.conf man page

这是代码:

from ftplib import FTP_TLS
import os
import socket

host = 'example.com'
port = 34567
user = 'user1'
passwd = 'pass123'
acct = 'Normal'

ftps = FTP_TLS()

ftps.set_debuglevel(2)

ftps.connect(host, port)

print(ftps.getwelcome())
print(ftps.sock)

ftps.auth()

ftps.login(user, passwd, acct)

ftps.set_pasv(True)
ftps.prot_p()

print('Current directory:')
print(ftps.pwd())
files = ftps.dir()

ftps.quit()

我想安全地做到这一点,因此使用 FTP over TLS Explicit。我的想法是我可能需要操作Socketftplib 引用的类中的一些设置。更改服务器上的设置是不可能的。我已经使用 FileZilla 客户端成功测试了服务器,旧版本的 WinSCP 引发了同样的错误——尽管升级到最新版本修复了它。

有任何想法吗?

4

2 回答 2

22

现在可以通过这个类(FTP_TLS 的后代)轻松地为Python 3.6+修复它:

class MyFTP_TLS(ftplib.FTP_TLS):
    """Explicit FTPS, with shared TLS session"""
    def ntransfercmd(self, cmd, rest=None):
        conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest)
        if self._prot_p:
            conn = self.context.wrap_socket(conn,
                                            server_hostname=self.host,
                                            session=self.sock.session)  # this is the fix
        return conn, size
于 2017-04-09T00:22:42.397 回答
7

当您提到升级到最新版本修复了该问题时,它看起来比ftplib更可能是vsftpd问题。

如果您不能触摸服务器的设置,则对它进行子类化FTP_TLS可能有助于解决您的问题,尽管在我看来这是一个相当HACK,参考了这个 SO question & answers Python FTP TLS connection issue。您还可以从这个python 错误问题 19500中查看:

" 服务器坚持数据连接使用 TLS 缓存会话是合理的。这可能是先前数据
连接或清除控制连接的缓存。如果这是拒绝允许数据传输的原因,那么'522'回复
应该表明这一点。

注意:这对客户端设计有重要影响,但允许服务器通过 拒绝与先前经过身份验证的客户端执行完整协商
来最小化 TLS 协商期间使用的周期 。”

看来 vsftpd 服务器通过强制“控制和数据连接之间的 SSL 会话重用”来实现这一点。

http://scarybeastsecurity.blogspot.com/2009/02/vsftpd-210-released.html

查看Python核心库ftplib.py的源代码,没有任何关于数据连接与控制连接之间的SSL会话重用的想法(如果我在这里错了,请纠正我。我试过FTP_TLS.transfercmd(cmd [,休息])¶,没有工作)。

此问题在支持 FTPS、IE WinSCP 的其他 FTP 客户端上有详细记录:https ://winscp.net/tracker/668

请参阅附加的测试日志文件。在 vsftpd.conf 中将“require_ssl_reuse”设置为 true 的 vsftpd 服务器可以解决问题并且可以复制。

希望这可以帮助。

于 2014-10-19T16:34:00.093 回答