FTPES - требуется повторное использование сеанса

Итак, я пытаюсь подключиться к 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 через TLS Explicit. У меня есть идея, что мне может понадобиться управлять некоторыми настройками в классе Socket, на который ссылается FTPLib. Изменение настроек на сервере невозможно. Я успешно протестировал сервер с клиентом FileZilla, более старая версия WinSCP вызывала ту же ошибку - хотя исправление до новой версии исправило ее.

Есть идеи?

2 ответа

Теперь это может быть легко исправлено для Python 3.6+ с помощью этого класса (потомок FTP_TLS):

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

Скорее всего, это проблема vsftpd, чем ftplib, так как вы упомянули, что обновление до последней версии решило проблему.

При условии, что вы не можете коснуться настроек сервера, подкласс FTP_TLS может помочь решить вашу проблему, хотя, на мой взгляд, это довольно ХАК, на который ссылается этот SO вопрос и ответы на вопросы Python FTP TLS-соединения. Вы также можете взглянуть на эту ошибку питона 19500:

"Разумно, чтобы сервер настаивал на том, что подключение для передачи данных использует сеанс кэширования TLS. Это может быть кэш предыдущих данных
соединение или очищенное контрольное соединение. Если это является причиной отказа в разрешении передачи данных, то ответ "522"
должен указать это.

Примечание: это имеет важное влияние на дизайн клиента, но позволяет
серверы для минимизации циклов, используемых во время согласования TLS
отказ от проведения полных переговоров с ранее
аутентифицированный клиент."

Похоже, что сервер vsftpd реализовал именно это, принудив "повторное использование сеанса SSL между элементом управления и подключением к данным".

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

Глядя на исходный файл базовой библиотеки Python ftplib.py, нет никакого отношения к идее повторного использования сеанса SSL между соединением данных и соединением управления (поправьте меня, если я ошибаюсь. Я пробовал FTP_TLS.transfercmd(cmd[, отдых])), не работал).

Эта проблема хорошо документирована на других клиентах FTP, которые поддерживают FTPS, IE WinSCP: https://winscp.net/tracker/668

Смотрите прикрепленный файл журнала испытаний. Сервер vsftpd с параметром require_ssl_reuse, установленным в true в vsftpd.conf, справится с задачей и может быть воспроизведен.

Надеюсь это поможет.

Другие вопросы по тегам