5

これは、この質問のフォローアップです。TwistedTLSConnectionを介してデータが送信されなかった場合の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: 

問題は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
4

3 に答える 3

6

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

infoCallback()内で遭遇した問題は、SSL.Connectionから関連するTwistedProtocolインスタンスに戻る方法がわからないことです。

私がやりたいのは、接続が確立され、TLSハンドシェイクが完了した後、プロトコルインスタンスでコールバックを呼び出すことです。これにより、続行する前に、証明書の検証が自分の好みに合っていることを確認できます。

于 2011-09-11T02:38:33.643 に答える
4

SSLコンテキストオブジェクトは、「情報コールバック」(Context.set_info_callback)を使用して構成できます。これはSSL_CTX_set_info_callbackのラッパーです。残念ながら、単一接続のコールバックを指定するためのもう少し便利な(この場合)SSL_set_info_callbackは、pyOpenSSLによって公開されません。

特に、ハンドシェイクが完了すると、情報コールバックが呼び出されます。いくつかのアクロバットで、この通知を遅延またはプロトコルへの他のコールバックに変えることができるはずです。

詳細については、pyOpenSSLset_info_callbackのドキュメントおよびOpenSSLSSL_CTX_set_info_callbackのドキュメントを参照してください。

于 2011-02-10T14:01:31.343 に答える
0

loseConnection()ハンドシェイクの問題のため、信頼性の低いものを使用していることがわかりました。それを呼び出すことは可能であり、接続が完全に切断されることはありません。したがって、TLSの場合は常にabortConnection()代わりに使用します。ハンドシェイクの状態に関係なく、接続が閉じられていることを確認します。

于 2015-03-27T13:33:15.260 に答える