Twisted listenSSL virtualhosts

非 Y 不嫁゛ 提交于 2019-12-02 08:59:24

问题


Currently using a really simple Twisted NameVirtualHost coupled with some JSON config files to serve really basic content in one Site object. The resources being served by Twisted are all WSGI objects built in flask.

I was wondering on how to go about wrapping the connections to these domains with an SSLContext, since reactor.listenSSL takes one and only one context, it isn't readily apparent how to give each domain/subdomain it's own crt/key pair. Is there any way to set up named virtual hosting with ssl for each domain that doesn't require proxying? I can't find any Twisted examples that use NameVirtualHost with SSL, and they only thing I could get to work is hook on the reactor listening on port 443 with only one domain's context?

I was wondering if anyone has attempted this?

My simple server without any SSL processing:

https://github.com/DeaconDesperado/twsrv/blob/master/service.py


回答1:


TLS (the name for the modern protocol which replaces SSL) only very recently supports the feature you're looking for. The feature is called Server Name Indication (or SNI). It is supported by modern browsers on modern platforms, but not some older but still widely used platforms (see the wikipedia page for a list of browsers with support).

Twisted has no specific, built-in support for this. However, it doesn't need any. pyOpenSSL, upon which Twisted's SSL support is based, does support SNI.

The set_tlsext_servername_callback pyOpenSSL API gives you the basic mechanism to build the behavior you want. This lets you define a callback which is given access to the server name requested by the client. At this point, you can specify the key/certificate pair you want to use for the connection. You can find an example demonstrating the use of this API in pyOpenSSL's examples directory.

Here's an excerpt from that example to give you the gist:

def pick_certificate(connection):
    try:
        key, cert = certificates[connection.get_servername()]
    except KeyError:
        pass
    else:
        new_context = Context(TLSv1_METHOD)
        new_context.use_privatekey(key)
        new_context.use_certificate(cert)
        connection.set_context(new_context)

server_context = Context(TLSv1_METHOD)
server_context.set_tlsext_servername_callback(pick_certificate)

You can incorporate this approach into a customized context factory and then supply that context factory to the listenSSL call.




回答2:


Just to add some closure to this one, and for future searches, here is the example code for the echo server from the examples that prints the SNI:

from twisted.internet import ssl, reactor
from twisted.internet.protocol import Factory, Protocol

class Echo(Protocol):
    def dataReceived(self, data):
        self.transport.write(data)

def pick_cert(connection):
    print('Received SNI: ', connection.get_servername())

if __name__ == '__main__':
    factory = Factory()
    factory.protocol = Echo

    with open("keys/ca.pem") as certAuthCertFile:
        certAuthCert = ssl.Certificate.loadPEM(certAuthCertFile.read())

    with open("keys/server.key") as keyFile:
        with open("keys/server.crt") as certFile:
            serverCert = ssl.PrivateCertificate.loadPEM(
                keyFile.read() + certFile.read())

    contextFactory = serverCert.options(certAuthCert)

    ctx = contextFactory.getContext()
    ctx.set_tlsext_servername_callback(pick_cert)

    reactor.listenSSL(8000, factory, contextFactory)
    reactor.run()

And because getting OpenSSL to work can always be tricky, here is the OpenSSL statement you can use to connect to it:

openssl s_client -connect localhost:8000 -servername hello_world -cert keys/client.crt -key keys/client.key

Running the above python code against pyOpenSSL==0.13, and then running the s_client command above, will print this to the screen:

('Received SNI: ', 'hello_world')



回答3:


There is now a txsni project that takes care of finding the right certificates per request. https://github.com/glyph/txsni



来源:https://stackoverflow.com/questions/12149119/twisted-listenssl-virtualhosts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!