Search code examples
ssltwistedsnipyopenssl

Twisted SNI with deferreds


In our system, virtual hosts configuration is stored in redis. During connection setup, when the SNI is received, we would like to query redis for the correct certificate and key pair to use for the TLS connection and create a new Context instance with that attached.

The bulk of the code is similar to the accepted answer here: Twisted listenSSL virtualhosts

The issue we are facing is that, since accessing the certificates involves an additional network operation, we would like to make the set_tlsext_servername_callback function return a deferred.

Is there a way to tell Twisted/pyOpenSSL to wait until the deferred fires?

Edit: I found this link which seems promising, but falls short of providing a solution: https://mta.openssl.org/pipermail/openssl-dev/2015-January/000480.html


Solution

  • You can find an example of Twisted and SNI here: https://pypi.python.org/pypi/txsni. I would really, really like that callback to be able to take a Deferred. I think that the way to do this would be to pause the underlying transport from delivering any further bytes either in or out (stopReading/stopWriting) and then resume when the Deferred fires, after doing the rest of the SNI dance. However, I'm not even sure if this is possible with OpenSSL, because the SNI is received with the rest of ClientHello and you may need to be able to react immediately to serve the correct certificate. In this worst-possible-case scenario, you could feed the first chunk of bytes you receive into a dummy memory-BIO, wait for the TLS handshake, throw it away and never deliver any generated responses, and then don't initialize your "real" sub-transport until you've decided on which context object to use.

    Hope this helps - and if you figure it out, please contribute a patch to TxSNI or Twisted!