From bc59dee45c51fe98092eea6f1e57f3e8ec267742 Mon Sep 17 00:00:00 2001 From: Tyler Spivey Date: Mon, 12 Jun 2023 10:55:35 -0700 Subject: [PATCH 1/3] Add the --no-ssl option Add the --no-ssl option to support running without SSL using the PROXY protocol from HAProxy. --- server.py | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/server.py b/server.py index 9c6e8bc..d826d0d 100644 --- a/server.py +++ b/server.py @@ -13,6 +13,7 @@ from twisted.internet.protocol import Factory, defer, connectionDone from twisted.internet.task import LoopingCall from twisted.protocols.basic import LineReceiver +from twisted.protocols.haproxy._wrapper import HAProxyWrappingFactory from twisted.python import log, usage from twisted.internet.defer import Deferred from twisted.python.failure import Failure @@ -363,6 +364,9 @@ class Options(usage.Options): ["network-interface", "i", "::", "Interface to listen on"], ["port", "p", "6837", "Server port"], ] + optFlags = [ + ["no-ssl", "n", "Disable SSL"], + ] # Exclude from coverage as it's hard to unit test. @@ -370,20 +374,21 @@ def main() -> Deferred[None]: # pragma: no cover # Read options from CLI. config = Options() config.parseOptions() - # Open SSL keys. - privkey = open(config["privkey"]).read() - certData = open(config["certificate"], "rb").read() - chain = open(config["chain"], "rb").read() log.startLogging(sys.stdout) - # Initialise encryption - privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, privkey) - certificate = crypto.load_certificate(crypto.FILETYPE_PEM, certData) - chain = crypto.load_certificate(crypto.FILETYPE_PEM, chain) - contextFactory = ssl.CertificateOptions( - privateKey=privkey, - certificate=certificate, - extraCertChain=[chain], - ) + if not config["no-ssl"]: + # Initialise encryption + # Open SSL keys. + privkey = open(config["privkey"]).read() + certData = open(config["certificate"], "rb").read() + chain = open(config["chain"], "rb").read() + privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, privkey) + certificate = crypto.load_certificate(crypto.FILETYPE_PEM, certData) + chain = crypto.load_certificate(crypto.FILETYPE_PEM, chain) + contextFactory = ssl.CertificateOptions( + privateKey=privkey, + certificate=certificate, + extraCertChain=[chain], + ) # Initialise the server state machine state = ServerState() if os.path.isfile(config["motd"]): @@ -393,11 +398,15 @@ def main() -> Deferred[None]: # pragma: no cover state.motd = None # Set up the machinery of the server. factory = RemoteServerFactory(state) + wrapped = HAProxyWrappingFactory(factory) looper = LoopingCall(factory.pingConnectedClients) looper.start(PING_INTERVAL) factory.protocol = Handler # Start running the server. - reactor.listenSSL(int(config["port"]), factory, contextFactory, interface=config["network-interface"]) + if config["no-ssl"]: + reactor.listenTCP(int(config["port"]), wrapped, interface=config["network-interface"]) + else: + reactor.listenSSL(int(config["port"]), factory, contextFactory, interface=config["network-interface"]) reactor.run() return defer.Deferred() From 4c416f7ab9ee405d93b62e85e662ae884e1c1cb7 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:38:51 +1000 Subject: [PATCH 2/3] Fix pyright issue --- server.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server.py b/server.py index d826d0d..ad9ed30 100644 --- a/server.py +++ b/server.py @@ -371,6 +371,7 @@ class Options(usage.Options): # Exclude from coverage as it's hard to unit test. def main() -> Deferred[None]: # pragma: no cover + sslContext: ssl.CertificateOptions | None = None # Read options from CLI. config = Options() config.parseOptions() @@ -384,7 +385,7 @@ def main() -> Deferred[None]: # pragma: no cover privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, privkey) certificate = crypto.load_certificate(crypto.FILETYPE_PEM, certData) chain = crypto.load_certificate(crypto.FILETYPE_PEM, chain) - contextFactory = ssl.CertificateOptions( + sslContext = ssl.CertificateOptions( privateKey=privkey, certificate=certificate, extraCertChain=[chain], @@ -398,15 +399,15 @@ def main() -> Deferred[None]: # pragma: no cover state.motd = None # Set up the machinery of the server. factory = RemoteServerFactory(state) - wrapped = HAProxyWrappingFactory(factory) + wrappedFactory = HAProxyWrappingFactory(factory) looper = LoopingCall(factory.pingConnectedClients) looper.start(PING_INTERVAL) factory.protocol = Handler # Start running the server. if config["no-ssl"]: - reactor.listenTCP(int(config["port"]), wrapped, interface=config["network-interface"]) + reactor.listenTCP(int(config["port"]), wrappedFactory, interface=config["network-interface"]) else: - reactor.listenSSL(int(config["port"]), factory, contextFactory, interface=config["network-interface"]) + reactor.listenSSL(int(config["port"]), factory, sslContext, interface=config["network-interface"]) reactor.run() return defer.Deferred() From bb64264563415eebe73bd3ad8fa70c6b58b90696 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:43:23 +1000 Subject: [PATCH 3/3] Organize imports --- server.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index ad9ed30..45859a2 100644 --- a/server.py +++ b/server.py @@ -6,18 +6,18 @@ import time from collections import OrderedDict from logging import getLogger +from typing import Any, TypedDict, cast from OpenSSL import crypto from twisted.internet import reactor, ssl +from twisted.internet.defer import Deferred from twisted.internet.interfaces import ITCPTransport -from twisted.internet.protocol import Factory, defer, connectionDone +from twisted.internet.protocol import Factory, connectionDone, defer from twisted.internet.task import LoopingCall from twisted.protocols.basic import LineReceiver from twisted.protocols.haproxy._wrapper import HAProxyWrappingFactory from twisted.python import log, usage -from twisted.internet.defer import Deferred from twisted.python.failure import Failure -from typing import Any, TypedDict, cast logger = getLogger("remote-server")