SNI(服务器名称指示)与龙卷风

SNI (Server Name Indication) with tornado

如标题所述,我想了解如何将 SNI(服务器名称指示)与 tornado 网络服务器一起使用。

我希望能够根据给定请求的主机名出示特定证书。

在深入研究之后,我找到了使用来自 ssl.SSLContextsni_callback 的解决方案。

这将为您提供一个在建立 TLS 握手之前包含主机名的方法。

servername_callback 方法中,您可以根据主机名选择要加载的证书。

工作解决方案
import tornado.ioloop
import tornado.web
import tornado.httpserver
import ssl

class MainHandler(tornado.web.RequestHandler):

    def get(self):
        self.write('Hello, world')

application = tornado.web.Application([
    (r'/', MainHandler)
])

def servername_callback(sock, hostname, cb_context):
    # hostname contains the hostname that the client is requesting
    print("hostname", hostname)

    # now that we have the hostname we can dynamically pick the correct certificate
    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    # this part is up to you to store via a config file or even in a database
    ssl_context.load_cert_chain(certfile="/path/to/cert", keyfile="/path/to/key")

    sock.context = ssl_context

if __name__ == '__main__':

    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    ssl_context.sni_callback = servername_callback

    http_server = tornado.httpserver.HTTPServer(application, ssl_options=ssl_context)
    http_server.listen(443)

    tornado.ioloop.IOLoop.instance().start()