我开始考虑通过扩展当前的 Twisted FTP 来实现显式 FTP。
大部分代码都很简单,实现 AUTH、PBSZ、PROT 很容易,我得到了一个有效的安全控制 channel 。
我的问题是数据通道。
客户端错误是:SSL routines', 'SSL3_READ_BYTES', 'ssl handshake failure'
看起来只有当某些数据通过数据通道发送时才会调用 SSL 握手和关闭。 这会影响发送空文件或列出空文件夹的情况,因为在关闭连接之前,客户端将调用 SSL 关闭。
我正在寻找一些关于在没有数据发送时应该如何以及在何处搜索以修复 Twisted TLS 中的 TLS 握手的建议。
此代码在列出非空文件夹时有效...但如果文件夹不包含任何文件或文件夹,则会失败。
非常感谢!
def getDTPPort(self, factory):
"""
Return a port for passive access, using C{self.passivePortRange}
attribute.
"""
for portn in self.passivePortRange:
try:
if self.protected_data:
dtpPort = reactor.listenSSL(
port=portn, factory=factory,
contextFactory=self.ssl_context)
else:
dtpPort = self.listenFactory(portn, factory)
except error.CannotListenError:
continue
else:
return dtpPort
raise error.CannotListenError('', portn,
"No port available in range %s" %
(self.passivePortRange,))
更新1
由于评论格式不正确,我将更新此文本:
最后我得到了:
def getDTPPort(self, factory):
"""
Return a port for passive access, using C{self.passivePortRange}
attribute.
"""
for portn in self.passivePortRange:
try:
if self.protected_data:
tls_factory = TLSMemoryBIOFactory(
contextFactory=self.ssl_context,
isClient=False,
wrappedFactory=factory)
dtpPort = reactor.listenTCP(
port=portn, factory=tls_factory)
else:
dtpPort = self.listenFactory(portn, factory)
except error.CannotListenError:
continue
else:
return dtpPort
raise error.CannotListenError('', portn,
"No port available in range %s" %
(self.passivePortRange,))
更新2
问题是在握手还在运行的时候连接被关闭造成的。 我不知道如何检查 SSL 握手已完成的空连接。
所以我得到了这个愚蠢的代码
def loseConnection(self):
"""
Send a TLS close alert and close the underlying connection.
"""
self.disconnecting = True
def close_connection():
if not self._writeBlockedOnRead:
self._tlsConnection.shutdown()
self._flushSendBIO()
self.transport.loseConnection()
# If we don't know if the handshake was done, we wait for a bit
# and the close the connection.
# This is done to avoid closing the connection in the middle of a
# handshake.
if not self._handshakeDone:
reactor.callLater(0.1, close_connection)
else:
close_connection()
最佳答案
SSL 握手由 pyOpenSSL 的 do_handshake
方法发起 Connection
目的。它也可以通过 send
或 recv
调用隐式启动。 reactor.connectSSL
和 reactor.listenSSL
建立的传输依赖于后者。所以您的结论是正确的 - 如果没有数据通过连接发送,则永远不会执行握手。
然而,twisted.protocols.tls
建立连接后立即调用 do_handshake
。如果您改为使用该 API 设置 SSL 服务器,我想您会发现问题已解决。
还有计划reimplement the former using the latter ,因为后者似乎总体上效果更好。
关于twisted - 没有数据通过 Twisted TLSConnection 发送时 SSL 握手失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4942121/