如何检查 TLS 握手是否已在 Twisted 中完成
这是这个问题的后续:SSL握手失败当没有数据通过Twisted TLSConnection发送
我已经实现了一个简单的SSL服务器客户端连接后立即关闭连接。
我正在使用 openssl 对其进行测试,并且出现握手失败:
$ openssl s_client -connect localhost:12345
CONNECTED(00000003) 2329:error:140790E5:SSL routines:SSL23_WRITE
:ssl handshake failure:s23_lib.c:188:
问题是 TLS.Connection.loseConnection
不会等待正在进行的握手完成,而只是断开客户端连接。
附加到 OpenSSL.SSL.Connection.do_handshake 的回调会很棒...但不幸的是我不知道这是否可以完成...或者如何做到。
非常感谢任何有关我如何测试 TLS 握手是否完成的提示。非常感谢!
这是代码
class ApplicationProtocol(Protocol):
'''Protocol that closes the connection when connection is made.'''
def connectionMade(self):
self.transport.loseConnection()
# Here is a barebone TLS Server
serverFactory = ServerFactory()
serverFactory.protocol = ApplicationProtocol
server_cert_path = 'server.pem'
serverContextFactory = DefaultOpenSSLContextFactory(
privateKeyFileName = server_cert_path,
certificateFileName = server_cert_path,
sslmethod=SSL.SSLv23_METHOD)
tlsFactory = TLSMemoryBIOFactory(serverContextFactory, False, serverFactory)
reactor.listenTCP(12345, tlsFactory)
#reactor.listenSSL(12345, serverFactory, serverContextFactory)
,现在我解决这个问题确实很脏,而且不是 100% 有效。
def tls_lose_connection(self):
"""
Monkey patching for TLSMemoryBIOProtocol to wait for handshake to end,
before closing the connection.
Send a TLS close alert and close the underlying connection.
"""
def close_connection():
self.disconnecting = True
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.5, close_connection)
else:
close_connection()
TLSMemoryBIOProtocol.loseConnection = tls_lose_connection
This is a follow up of this question: SSL handshake failures when no data was sent over Twisted TLSConnection
I have implemented a simple SSL server that closes the connection as soon as the client is connected.
I am testing it with openssl and I got this handshake failure:
$ openssl s_client -connect localhost:12345
CONNECTED(00000003) 2329:error:140790E5:SSL routines:SSL23_WRITE
:ssl handshake failure:s23_lib.c:188:
The problem is that TLS.Connection.loseConnection
does not wait for the ongoing handshake to be done and just disconnects the client.
A callback attached to OpenSSL.SSL.Connection.do_handshake
would have been great... but unfortunately I don't know if this can be done... or how to do it.
Any hints in how I could test that a TLS handshake was done is much appreciated. Many thanks!
Here is the code
class ApplicationProtocol(Protocol):
'''Protocol that closes the connection when connection is made.'''
def connectionMade(self):
self.transport.loseConnection()
# Here is a barebone TLS Server
serverFactory = ServerFactory()
serverFactory.protocol = ApplicationProtocol
server_cert_path = 'server.pem'
serverContextFactory = DefaultOpenSSLContextFactory(
privateKeyFileName = server_cert_path,
certificateFileName = server_cert_path,
sslmethod=SSL.SSLv23_METHOD)
tlsFactory = TLSMemoryBIOFactory(serverContextFactory, False, serverFactory)
reactor.listenTCP(12345, tlsFactory)
#reactor.listenSSL(12345, serverFactory, serverContextFactory)
For now I solve this really dirty and not 100% valid.
def tls_lose_connection(self):
"""
Monkey patching for TLSMemoryBIOProtocol to wait for handshake to end,
before closing the connection.
Send a TLS close alert and close the underlying connection.
"""
def close_connection():
self.disconnecting = True
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.5, close_connection)
else:
close_connection()
TLSMemoryBIOProtocol.loseConnection = tls_lose_connection
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我提供了实现让-保罗答案的代码。
我在 infoCallback() 内部遇到的问题是我不知道如何从 SSL.Connection 返回到关联的 Twisted Protocol 实例。
我想要做的是在建立连接并完成 TLS 握手后在我的协议实例上调用回调,这样我就可以在继续之前确保证书验证符合我的喜好。
I'm providing code that implements Jean-Paul's answer.
The problem I ran into inside of infoCallback() is that I have no idea how to get from the SSL.Connection back to the associated Twisted Protocol instance.
What I'd like to do is invoke a callback on my Protocol instance after the connection has been made and the TLS handshake has been completed so I can be sure the certificate validation is to my liking before I proceed.
SSL 上下文对象可以使用“信息回调”进行配置 - Context.set_info_callback。这是 SSL_CTX_set_info_callback 的包装。不幸的是,pyOpenSSL 没有公开稍微方便一点(在本例中)的用于为单个连接指定回调的 SSL_set_info_callback 。
除此之外,握手完成时会调用信息回调。通过一些技巧,您应该能够将此通知转换为延迟或协议上的其他回调。
请参阅 pyOpenSSL set_info_callback 文档 和 OpenSSL SSL_CTX_set_info_callback 文档了解详细信息。
The SSL context object can be configured with an "info callback" - Context.set_info_callback. This is a wrapper around SSL_CTX_set_info_callback. The slightly more convenient (in this case) SSL_set_info_callback for specifying a callback for a single connection is not exposed by pyOpenSSL, unfortunately.
Amongst other things, the info callback is invoked when the handshake completes. With a few acrobatics, you should be able to turn this notification into a Deferred or some other callback onto the protocol.
See the pyOpenSSL set_info_callback documentation and the OpenSSL SSL_CTX_set_info_callback documentation for details.
我发现由于握手问题,使用
loseConnection()
不可靠。可以调用它并且连接永远不会完全断开。因此,对于 TLS,我总是使用abortConnection()
代替。无论握手的状态如何,它将确保连接关闭。I found using
loseConnection()
unreliable because of the handshaking issue. It's possible to call it and the connection is never fully disconnected. So, for TLS I always useabortConnection()
instead. It will make sure the connection is closed regardless of the state of the handshake.