Подключение к FTP TLS 1.2 Server с ftplib

Я пытаюсь подключиться к FTP-серверу, который поддерживает только TLS 1.2. Использование Python 3.4.1

Мой код:

import ftplib import ssl ftps = ftplib.FTP_TLS() ftps.ssl_version = ssl.PROTOCOL_TLSv1_2 print (ftps.connect('108.61.166.122',31000)) print(ftps.login('test','test123')) ftps.prot_p() print (ftps.retrlines('LIST')) 

Ошибка на стороне клиента:

 ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:598) 

Ошибка на стороне сервера:

  Failed TLS negotiation on control channel, disconnected. (SSL_accept(): error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol) 

Учетные данные в этом примере работают для тестирования.

См. Конец этого сообщения для окончательного решения. Остальные – это шаги, необходимые для отладки проблемы.

Я пытаюсь подключиться к FTP-серверу, который поддерживает только TLS 1.2. Использование Python 3.4.1

Откуда вы знаете?

ssl.SSLEOFError: EOF произошел с нарушением протокола (_ssl.c: 598)

Я бы предложил одну из многих проблем SSL между клиентом и сервером, например, сервер, не поддерживающий TLS 1.2, не общие шифры и т. Д. Эти проблемы трудно отлаживать, потому что вы либо получаете только некоторое оповещение по SSL, либо сервер просто закрывает соединение без любая очевидная причина. Если у вас есть доступ к серверу, найдите сообщения об ошибках на стороне сервера.

Вы также можете попытаться не применять SSL-версию, но использовать по умолчанию вместо этого, чтобы клиент и сервер согласились с лучшей версией SSL. Если это еще не сработает, попробуйте с клиентом, который, как известно, работает с этим сервером и делает пакетный захват хороших и плохих соединений и сравнивает. Если вам нужна помощь с этим сообщением, пакет захватывает облачный форум.

Редактировать # 1: попробовал только с python 3.4.0 и 3.4.2 против тестового сервера:

  • python 3.4.0 выполняет рукопожатие TLS 1.0, т.е. игнорирует настройку
  • python 3.4.2 делает успешное рукопожатие TLS 1.2

В обеих версиях ftplib имеет незначительную ошибку, что он отправляет AUTH SSL вместо AUTH TLS если ftps.ssl_version – это что-то другое, чем TLS 1.0, то есть SSLv3 или TLS1.1. +. Хотя я сомневаюсь, что это причина проблемы, на самом деле это может быть, если FTP-сервер обрабатывает AUTH TLS и AUTH SSL разному.

Редактировать # 2 и решение:

ftps.ssl_version захват показывает, что установка ftps.ssl_version не имеет эффекта, и SSL-квитирование все равно будет выполняться только с TLS 1.0. Глядя на исходный код ftplib в 3.4.0, вы получаете:

  ssl_version = ssl.PROTOCOL_TLSv1 def __init__(self, host='', user='', passwd='', acct='', keyfile=None, certfile=None, context=None, timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None): .... if context is None: context = ssl._create_stdlib_context(self.ssl_version, certfile=certfile, keyfile=keyfile) self.context = context 

Поскольку __init__ вызывается, когда ftplib.FTP_TLS() называется контекстом SSL, будет создан с использованием ssl_version по умолчанию, используемым ftplib ( ssl.PROTOCOL_TLSv1 ), а не с вашей собственной версией. Чтобы применить другую версию SSL, вы должны предоставить свой собственный контекст с необходимой версией SSL. Для меня работает следующее:

 import ftplib import ssl ctx = ssl._create_stdlib_context(ssl.PROTOCOL_TLSv1_2) ftps = ftplib.FTP_TLS(context=ctx) print (ftps.connect('108.61.166.122',31000)) print(ftps.login('test','test123')) ftps.prot_p() print (ftps.retrlines('LIST')) 

В качестве альтернативы вы можете установить версию протокола глобально, а не только для этого объекта FTP_TLS:

 ftplib.FTP_TLS.ssl_version = ssl.PROTOCOL_TLSv1_2 ftps = ftplib.FTP_TLS() 

И просто небольшое, но важное наблюдение: похоже, что ftplib не выполняет никакой проверки сертификата , так как он принимает этот самозаверяющий сертификат, который не соответствует имени без жалоб. Это делает возможной атаку «человек в середине». Надеюсь, они исправит это небезопасное поведение в будущем, и в этом случае код здесь потерпит неудачу из-за недействительного сертификата.

Во-первых, AFAIK no ftp напрямую поддерживает SSL, для чего вводится ftps. Кроме того, sftp и ftps – это две разные концепции: http://en.wikipedia.org/wiki/FTPS. Теперь ваша проблема связана с программированием и не связана с SSL или FTP-серверами или с любой такой клиент-серверной связью

 import ftplib import ssl ftps = ftplib.FTP_TLS() #ftps.ssl_version = ssl.PROTOCOL_TLSv1_2 print (ftps.connect('108.61.166.122',31000)) print(ftps.login('test','test123')) ftps.prot_p() print (ftps.retrlines('LIST')) 

поскольку ftplib не имеет атрибута PROTOCOL_TLSv1_2, кроме которого он работает нормально. и хорошо, ваш хост не отвечает!

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