Created
July 31, 2017 00:48
-
-
Save derwolfe/5a4a1ee7d578b1458f765ed1692dcd0a to your computer and use it in GitHub Desktop.
twisted site with HSTS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import pem | |
from twisted.application.service import Application | |
from twisted.application.internet import ( | |
TCPServer, | |
SSLServer | |
) | |
from twisted.python.filepath import FilePath | |
from twisted.web.server import Site | |
from twisted.web.static import File | |
from twisted.web.resource import Resource | |
from twisted.web.util import redirectTo | |
from twisted.web._responses import NOT_FOUND | |
from twisted.internet.ssl import ( | |
CertificateOptions, | |
Certificate, | |
PrivateCertificate | |
) | |
SECURE_PORT = 443 | |
dhParamPath = FilePath('/home/webserver/ssl-keys/dhparam.pem') | |
ctxFactory = pem.certificateOptionsFromFiles( | |
'/home/webserver/ssl-keys/www.derwolfe.net.key', | |
'/home/webserver/ssl-keys/www.derwolfe.net.chained.crt', | |
dhParameters=pem.DiffieHellmanParameters.fromFile(dhParamPath) | |
) | |
class RedirectResource(Resource): | |
isLeaf = True | |
def render(self, request): | |
host = request.requestHeaders.getRawHeaders('host')[0].split(':', 1)[0] | |
port = '' | |
if SECURE_PORT is not None: | |
port = ':{0}'.format(SECURE_PORT) | |
return redirectTo( | |
'https://{0}{1}{2}'.format(host, port, request.uri), | |
request | |
) | |
class HSTSResource(Resource): | |
def __init__(self, wrapped): | |
self._wrapped = wrapped | |
def getChildWithDefault(self, name, request): | |
request.responseHeaders.addRawHeader( | |
'Strict-Transport-Security', | |
'max-age=31536000; includeSubDomains' | |
) | |
return self._wrapped.getChildWithDefault(name, request) | |
class ErrorResource(Resource): | |
""" | |
Return a custom 404 page | |
""" | |
def __init__(self, status): | |
Resource.__init__(self) | |
self.status = status | |
self.page = self._readTemplate() | |
def _readTemplate(self): | |
with open('/home/webserver/site/error/index.html', 'r') as f: | |
return f.read() | |
def render(self, request): | |
request.setResponseCode(self.status) | |
request.setHeader(b"content-type", b"text/html; charset=utf-8") | |
return self.page | |
def getChild(self, chnam, request): | |
return self | |
class NoResource(ErrorResource): | |
def __init__(self): | |
ErrorResource.__init__(self, NOT_FOUND) | |
application = Application("My website") | |
plainSite = Site(RedirectResource()) | |
plainSite.displayTracebacks = False | |
plainService6 = TCPServer(80, plainSite, interface='::') | |
plainService6.setServiceParent(application) | |
files = File('/home/webserver/site') | |
files.childNotFound = NoResource() | |
secureSite = Site(HSTSResource(files)) | |
secureSite.displayTracebacks = False | |
secureService6 = SSLServer(443, | |
secureSite, | |
ctxFactory, | |
interface='::') | |
secureService6.setServiceParent(application) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment