2015-05-16 10 views
5

Ich versuche, auf einen FTP-Server zu verbinden, die TLS unterstützt nur 1.2 Python 3.4.1eine Verbindung zum FTP-TLS 1.2 Server mit ftplib

Mein Code:

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')) 

Fehler auf Client-Seite:

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

Fehler auf Server-Seite:

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

Die Anmeldeinformationen in diesem Beispiel funktionieren zum Testen.

+0

Es wäre sehr hilfreich, wenn Sie eine Paketerfassung der Verbindung bereitstellen könnten (Beitrag zu cloudshark.org). –

+0

@ W0bble: Sind Sie sicher, dass Sie ftps: // ein nicht sftp wollen. – user2284570

Antwort

2

Siehe das Ende dieses Beitrags für die endgültige Lösung. Der Rest sind die Schritte, um das Problem zu beheben.

I try to connect to a FTP Server which only supports TLS 1.2 Using Python 3.4.1

Woher kennen Sie?

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

würde ich eine der vielen SSL-Probleme zwischen Client und Server vorschlagen, wie der Server nicht TLS unterstützt 1.2, keine gemeinsamen Chiffren usw. Diese Probleme sind schwer zu debuggen, weil Sie entweder nur eine SSL-Benachrichtigung erhalten, oder die Der Server schließt die Verbindung ohne ersichtlichen Grund. Wenn Sie Zugriff auf den Server haben, suchen Sie auf der Serverseite nach Fehlermeldungen.

Sie auch nicht versuchen, eine SSL-Version zu erzwingen, aber den Standard stattdessen verwenden, so dass Client und Server der besten SSL-Version unterstützt beide zustimmen. Wenn dies immer noch nicht funktioniert, versuchen Sie es mit einem Client, der bekanntermaßen mit diesem Server arbeitet und eine Paketerfassung der guten und schlechten Verbindungen vornimmt und vergleicht. Wenn Sie Hilfe mit diesem Beitrag benötigen, wird das Paket auf cloudshark.org erfasst.

Edit # 1: gerade versucht es mit Python 3.4.0 und 3.4.2 gegen einen Testserver:

  • Python 3.4.0 funktioniert ein TLS 1.0-Handshake, ignoriert also die Einstellung
  • Python 3.4 0,2 funktioniert einem erfolgreichen TLS 1.2 Handshake

In beiden Versionen ftplib die kleinere Bug hat, dass es AUTH SSL statt AUTH TLS sendet, wenn ftps.ssl_version etwas anderes dann TLS 1.0, dh SSLv3 oder TLS1.1. +. Während ich bezweifle, dass dies der Ursprung des Problems ist, könnte es tatsächlich sein, wenn der FTP-Server AUTH TLS und AUTH SSL anders behandelt.

Edit # 2 und Lösung:

Eine Paketerfassung zeigt, dass ftps.ssl_version Einstellung keine Wirkung hat und der SSL-Handshake wird nach wie vor mit TLS 1.0 nur durchgeführt werden. Mit Blick auf dem Quellcode ftplib in 3.4.0 gibt:

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 

Seit __init__ aufgerufen wird, wenn ftplib.FTP_TLS() der SSL Zusammenhang mit der Standard-ssl_version von ftplib verwendet erstellt genannt wird (ssl.PROTOCOL_TLSv1) und nicht mit Ihrer eigenen Version . Um eine andere SSL-Version zu erzwingen, müssen Sie einen eigenen Kontext mit der benötigten SSL-Version bereitstellen.Die folgenden Werke für mich:

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')) 

Alternativ können Sie die Protokollversion gesetzt global statt nur für dieses FTP_TLS Objekt:

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

Und nur eine kleine, aber wichtige Beobachtung: es sieht aus wie die ftplib macht keine Art von Zertifikatsüberprüfung, da es dieses selbstsignierte Zertifikat akzeptiert, das nicht mit dem Namen übereinstimmt, ohne sich zu beschweren. Dies ermöglicht einen aktiven Man-in-the-Middle-Angriff. Hoffentlich werden sie dieses unsichere Verhalten in der Zukunft beheben, in welchem ​​Fall der Code hier wegen eines ungültigen Zertifikats fehlschlägt.

+0

Ich weiß es, weil ich es eingerichtet habe. Wenn ich die Zeile entferne: ftps.ssl_version = ssl.PROTOCOL_TLSv1_2 bekomme ich ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] falsche Versionsnummer (_ssl.c: 598 – W0bble

+0

Ein richtiger Setup-Server wird das verwendete Protokoll aushandeln. Welche Art von Server ist das? ? Wie ist es Setup? Kannst du Warnungen oder Fehler auf der Server-Seite sehen? Arbeiten andere Clients mit diesem Server? –

+0

Es ist ein Glftpd-Server und jeder andere Client wie Filezilla ftprush usw. funktionieren. (Alle Clients, die den Standard openssl verwenden Bibliotheken) Es ist defenitly ein python Problem Fehler auf Server-Seite:.. fehlgeschlagen TLS Verhandlungen über Steuerkanal getrennt (SSL_accept(): (1) Fehler: 140760FC: SSL-Routinen: SSL23_GET_CLIENT_HELLO: unbekanntes Protokoll) – W0bble

-1

Erstens AFAIK no ftp unterstützt SSL direkt, für die ftps eingeführt wird. Auch sftp und ftps sind zwei unterschiedliche Konzepte: http://en.wikipedia.org/wiki/FTPS .Jetzt, Ihr Problem ist die Programmierung über und nicht auf SSL oder FTPS oder eine solche Client-Server-Kommunikation

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')) 

als ftplib kein Attribut hat im Zusammenhang PROTOCOL_TLSv1_2 neben dem es funktioniert fein. und gut, Ihr Gastgeber antwortet nicht!

Hoffentlich hilft es!

+0

Python 3 (die hier verwendet wird) hat das erforderliche Attribut. –