Adi*_*ban 4 ssl openssl twisted pyopenssl
这是对此问题的跟进:当没有数据通过Twisted TLSConnection发送时,SSL握手失败
我已经实现了一个简单的SSL服务器,一旦客户端连接就关闭连接.
我用openssl测试它,我得到了这次握手失败:
$ openssl s_client -connect localhost:12345
CONNECTED(00000003) 2329:error:140790E5:SSL routines:SSL23_WRITE
:ssl handshake failure:s23_lib.c:188:
Run Code Online (Sandbox Code Playgroud)
问题是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)
Run Code Online (Sandbox Code Playgroud)
现在我解决这个问题非常脏,而且不是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
Run Code Online (Sandbox Code Playgroud)
我提供的代码实现了Jean-Paul的答案.
class ProxyClientTLSContextFactory(ssl.ClientContextFactory):
isClient = 1
def getContext(self):
ctx = SSL.Context(SSL.TLSv1_METHOD)
logger = logging.GetLogger()
def infoCallback(conn, where, ret):
# conn is a OpenSSL.SSL.Connection
# where is a set of flags telling where in the handshake we are
# See http://www.openssl.org/docs/ssl/SSL_CTX_set_info_callback.html
logger.debug("infoCallback %s %d %d" % (conn, where, ret))
if where & SSL.SSL_CB_HANDSHAKE_START:
logger.debug("Handshake started")
if where & SSL.SSL_CB_HANDSHAKE_DONE:
logger.debug("Handshake done")
ctx.set_info_callback(infoCallback)
return ctx
Run Code Online (Sandbox Code Playgroud)
我在infoCallback()内部遇到的问题是我不知道如何从SSL.Connection返回到相关的Twisted Protocol实例.
我想做的是在建立连接并完成TLS握手后调用我的Protocol实例上的回调,这样我就可以确保在继续之前证书验证是我喜欢的.
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 文档。
| 归档时间: |
|
| 查看次数: |
3572 次 |
| 最近记录: |