python自带的ftplib中有FTP_TLS类,支持连接带ssl的FTP。但implicitssl/tls FTP要求客户端在建立socket链接之后立刻用 ssl/tls 加密,否则不会发送欢迎信息。由于FTP_TLS并没有重载基类FTP的connect方法,因此并不能和implicit ssl/tls FTP正确连接。我们需要修改FTP_TLS来解决次问题。采用继承的方法,代码如下:
class tyFTP(FTP_TLS):
def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
certfile=None, timeout=60):
FTP_TLS.__init__(self, host, user, passwd, acct, keyfile, certfile, timeout)
def connect(self, host='', port=0, timeout=-999):
'''Connect to host. Arguments are:
- host: hostname to connect to (string, default previous host)
- port: port to connect to (integer, default previous port)
'''
if host != '':
self.host = host
if port > 0:
self.port = port
if timeout != -999:
self.timeout = timeout
try:
self.sock = socket.create_connection((self.host, self.port), self.timeout)
self.af = self.sock.family
#add this line!!!
self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile,ssl_version=ssl.PROTOCOL_TLSv1)
#add end
self.file = self.sock.makefile('rb')
self.welcome = self.getresp()
except Exception as e:
print e
return self.welcome
这样就能成功connect到implicit ssl/tls ftp的端口了(一般是990)。login也不会有问题。在login之后需要调用prot_p()方法,标明之后的数据通信都进行 ssl/tls 加密,才能正确的执行ftp指令。
关于implicit ssl/tls ftp,大概介绍如下:
以FTP/SSL为例:
隐式TLS-服务器在990端口监听,客户端建立TCP连接,然后建立SSL连接,然后进行USER PASS的ftp 认证。其间是没有 AUTH TLS这种特殊command的。
显式TLS-服务器仍然在21端口监听,客户端正常发起tcp连接、服务器返回hello、客户端发起AUTH TLS-至此建立了TLS认证,以后才是加密状态。如果服务器设置了必须使用TLS,则当server hello后,客户端试图不建立SSL连接而直接进行USER PASS的ftp认证,服务器会踢掉客户端。
简而言之:
隐式TLS-干脆利落,服务器listen一个单独端口,上来就直接SSL加密,然后才建立应用层会话。
显式TLS-保持最大的兼容性,还是混在原来的端口,只是应用层会话一旦建立,就用特殊的命令来建立SSL会话。
所谓隐式TLS/显式TLS,区别主要在是否独立开监听端口上。
隐式TLS的实现,都是要求服务器单独listen一个特殊端口,客户端连接后直接建立SSL会话,然后再进行应用协议的command,整个过程都是加密的;而显式TLS的实现,是在原应用协议的基础上改进,增加了TLS认证的command,并且server不占用单独的端口。