From 6e3c69eaf731279382aa39117f79fdb1bfbbf878 Mon Sep 17 00:00:00 2001 From: Florent D'halluin Date: Tue, 5 Apr 2016 00:13:30 +0200 Subject: [PATCH] add ssl support (required for any browser use of h2) --- daphne/cli.py | 17 +++++++++++++++++ daphne/server.py | 33 +++++++++++++++++++++++++++------ setup.py | 3 ++- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/daphne/cli.py b/daphne/cli.py index 415f547..d075286 100755 --- a/daphne/cli.py +++ b/daphne/cli.py @@ -74,11 +74,25 @@ class CommandLineInterface(object): help="enable HTTP/2" ) + self.parser.add_argument( + '--sslcert', + action="store", + help="path to ssl certificate file" + ) + + self.parser.add_argument( + '--sslkey', + action="store", + help="path to ssl private key file" + ) + + self.parser.add_argument( 'channel_layer', help='The ASGI channel layer instance to use as path.to.module:instance.path', ) + @classmethod def entrypoint(cls): """ @@ -137,4 +151,7 @@ class CommandLineInterface(object): http_timeout=args.http_timeout, ping_interval=args.ping_interval, action_logger=AccessLogGenerator(access_log_stream) if access_log_stream else None, + ssl_certificate=args.sslcert, + ssl_key=args.sslkey + ).run() diff --git a/daphne/server.py b/daphne/server.py index 1188f66..bac05b9 100755 --- a/daphne/server.py +++ b/daphne/server.py @@ -1,5 +1,6 @@ import logging -from twisted.internet import reactor +from twisted.internet import reactor, ssl, endpoints +from OpenSSL import crypto from .http_protocol import HTTPFactory @@ -20,6 +21,8 @@ class Server(object): http_timeout=120, websocket_timeout=None, ping_interval=20, + ssl_certificate = None, + ssl_key = None ): self.channel_layer = channel_layer self.host = host @@ -33,7 +36,9 @@ class Server(object): # channel layer's group_expiry value if present, or one day if not. self.websocket_timeout = websocket_timeout or getattr(channel_layer, "group_expiry", 86400) self.factory_class = factory_class - + self.ssl_certificate = ssl_certificate + self.ssl_key = ssl_key + def run(self): self.factory = self.factory_class( self.channel_layer, @@ -42,10 +47,26 @@ class Server(object): websocket_timeout=self.websocket_timeout, ping_interval=self.ping_interval, ) - if self.unix_socket: - reactor.listenUNIX(self.unix_socket, self.factory) - else: - reactor.listenTCP(self.port, self.factory, interface=self.host) + + if self.ssl_certificate : + with open(self.ssl_certificate, 'r') as f: + cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read()) + with open(self.ssl_key, 'r') as f: + key = crypto.load_privatekey(crypto.FILETYPE_PEM, f.read()) + + opts = ssl.CertificateOptions( + privateKey= key, + certificate=cert, + acceptableProtocols=[b'h2'] + ) + + endpt = endpoints.SSL4ServerEndpoint(reactor, self.port, opts, backlog=128) + endpt.listen(self.factory) + else : + if self.unix_socket: + reactor.listenUNIX(self.unix_socket, self.factory) + else: + reactor.listenTCP(self.port, self.factory, interface=self.host) reactor.callLater(0, self.backend_reader) reactor.callLater(2, self.timeout_checker) reactor.run(installSignalHandlers=self.signal_handlers) diff --git a/setup.py b/setup.py index 2be72dd..eddd2fb 100755 --- a/setup.py +++ b/setup.py @@ -24,7 +24,8 @@ setup( 'asgiref>=0.10', 'twisted>=15.5', 'autobahn>=0.12', - 'h2>=2.2' + 'h2>=2.2', + 'pyOpenSSL' # optionnal ?? ], entry_points={'console_scripts': [ 'daphne = daphne.cli:CommandLineInterface.entrypoint',