From: Chris Porter Date: Fri, 31 Jul 2009 00:09:45 +0000 (+0100) Subject: Add HTTP X-Forwarded-For support (fixes issue 30). X-Git-Url: https://jfr.im/git/irc/quakenet/qwebirc.git/commitdiff_plain/23f85e9bad08d386c5fb55b1f03c6140b3eb05be Add HTTP X-Forwarded-For support (fixes issue 30). --- diff --git a/config.py.example b/config.py.example index ac727d9..36871a2 100644 --- a/config.py.example +++ b/config.py.example @@ -118,6 +118,20 @@ FEEDBACK_SMTP_HOST, FEEDBACK_SMTP_PORT = "127.0.0.1", 25 # http://instance/adminengine ADMIN_ENGINE_HOSTS = ["127.0.0.1"] +# PROXY OPTIONS +# --------------------------------------------------------------------- +# +# OPTION: FORWARDED_FOR_HEADER +# If you're using a proxy that passes through a forwarded-for +# header set this option to the header name, also set +# FORWARDED_FOR_IPS. +#FORWARDED_FOR_HEADER="x-forwarded-for" + +# OPTION: FORWARDED_FOR_IPS +# This option specifies the IP addresses that forwarded-for +# headers will be accepted from. +#FORWARDED_FOR_IPS=["127.0.0.1"] + # EXECUTION OPTIONS # --------------------------------------------------------------------- # diff --git a/qwebirc/engines/ajaxengine.py b/qwebirc/engines/ajaxengine.py index a7acb46..a6aca3e 100644 --- a/qwebirc/engines/ajaxengine.py +++ b/qwebirc/engines/ajaxengine.py @@ -183,7 +183,7 @@ class AJAXEngine(resource.Resource): def newConnection(self, request): ticket = login_optional(request) - _, ip, port = request.transport.getPeer() + ip = request.getClientIP() nick = request.args.get("nick") if not nick: diff --git a/qwebirc/root.py b/qwebirc/root.py index 99464c1..73d039a 100644 --- a/qwebirc/root.py +++ b/qwebirc/root.py @@ -4,6 +4,7 @@ import engines import mimetypes import config import sigdebug +import re class RootResource(resource.Resource): def getChild(self, name, request): @@ -35,10 +36,36 @@ class TimeoutHTTPChannel(http.HTTPChannel): self.cancelTimeout() http.HTTPChannel.connectionLost(self, reason) +class ProxyRequest(server.Request): + ip_re = re.compile(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$") + def validIP(self, ip): + m = self.ip_re.match(ip) + if m is None: + return False + return all(int(m.group(x)) < 256 for x in range(1, 4+1)) + + def getClientIP(self): + real_ip = http.Request.getClientIP(self) + if real_ip not in config.FORWARDED_FOR_IPS: + return real_ip + + fake_ips = self.getHeader(config.FORWARDED_FOR_HEADER) + if fake_ips is None: + return real_ip + + fake_ip = fake_ips.split(",")[-1].strip() + if not self.validIP(fake_ip): + return real_ip + + return fake_ip + class RootSite(server.Site): # we do this ourselves as the built in timeout stuff is really really buggy protocol = TimeoutHTTPChannel + if hasattr(config, "FORWARDED_FOR_HEADER"): + requestFactory = ProxyRequest + def __init__(self, path, *args, **kwargs): root = RootResource() server.Site.__init__(self, root, *args, **kwargs)