Commit c3e785202b449a1a15030ea5fdfe8563c7b989c8
Add HTTP X-Forwarded-For support (fixes issue 30).
| | | | 118 | # http://instance/adminengine | 118 | # http://instance/adminengine |
---|
119 | ADMIN_ENGINE_HOSTS = ["127.0.0.1"] | 119 | ADMIN_ENGINE_HOSTS = ["127.0.0.1"] |
---|
120 | | 120 | |
---|
| | 121 | # PROXY OPTIONS |
---|
| | 122 | # --------------------------------------------------------------------- |
---|
| | 123 | # |
---|
| | 124 | # OPTION: FORWARDED_FOR_HEADER |
---|
| | 125 | # If you're using a proxy that passes through a forwarded-for |
---|
| | 126 | # header set this option to the header name, also set |
---|
| | 127 | # FORWARDED_FOR_IPS. |
---|
| | 128 | #FORWARDED_FOR_HEADER="x-forwarded-for" |
---|
| | 129 | |
---|
| | 130 | # OPTION: FORWARDED_FOR_IPS |
---|
| | 131 | # This option specifies the IP addresses that forwarded-for |
---|
| | 132 | # headers will be accepted from. |
---|
| | 133 | #FORWARDED_FOR_IPS=["127.0.0.1"] |
---|
| | 134 | |
---|
121 | # EXECUTION OPTIONS | 135 | # EXECUTION OPTIONS |
---|
122 | # --------------------------------------------------------------------- | 136 | # --------------------------------------------------------------------- |
---|
123 | # | 137 | # |
---|
| | | | 183 | def newConnection(self, request): | 183 | def newConnection(self, request): |
---|
184 | ticket = login_optional(request) | 184 | ticket = login_optional(request) |
---|
185 | | 185 | |
---|
186 | _, ip, port = request.transport.getPeer() | | _, ip, port = request.transport.getPeer() |
---|
| | 186 | ip = request.getClientIP() | 187 | | 187 | |
---|
188 | nick = request.args.get("nick") | 188 | nick = request.args.get("nick") |
---|
189 | if not nick: | 189 | if not nick: |
---|
| | | | 4 | import mimetypes | 4 | import mimetypes |
---|
5 | import config | 5 | import config |
---|
6 | import sigdebug | 6 | import sigdebug |
---|
| | 7 | import re |
---|
7 | | 8 | |
---|
8 | class RootResource(resource.Resource): | 9 | class RootResource(resource.Resource): |
---|
9 | def getChild(self, name, request): | 10 | def getChild(self, name, request): |
---|
… | | … | |
---|
36 | self.cancelTimeout() | 36 | self.cancelTimeout() |
---|
37 | http.HTTPChannel.connectionLost(self, reason) | 37 | http.HTTPChannel.connectionLost(self, reason) |
---|
38 | | 38 | |
---|
| | 39 | class ProxyRequest(server.Request): |
---|
| | 40 | ip_re = re.compile(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$") |
---|
| | 41 | def validIP(self, ip): |
---|
| | 42 | m = self.ip_re.match(ip) |
---|
| | 43 | if m is None: |
---|
| | 44 | return False |
---|
| | 45 | return all(int(m.group(x)) < 256 for x in range(1, 4+1)) |
---|
| | 46 | |
---|
| | 47 | def getClientIP(self): |
---|
| | 48 | real_ip = http.Request.getClientIP(self) |
---|
| | 49 | if real_ip not in config.FORWARDED_FOR_IPS: |
---|
| | 50 | return real_ip |
---|
| | 51 | |
---|
| | 52 | fake_ips = self.getHeader(config.FORWARDED_FOR_HEADER) |
---|
| | 53 | if fake_ips is None: |
---|
| | 54 | return real_ip |
---|
| | 55 | |
---|
| | 56 | fake_ip = fake_ips.split(",")[-1].strip() |
---|
| | 57 | if not self.validIP(fake_ip): |
---|
| | 58 | return real_ip |
---|
| | 59 | |
---|
| | 60 | return fake_ip |
---|
| | 61 | |
---|
39 | class RootSite(server.Site): | 62 | class RootSite(server.Site): |
---|
40 | # we do this ourselves as the built in timeout stuff is really really buggy | 63 | # we do this ourselves as the built in timeout stuff is really really buggy |
---|
41 | protocol = TimeoutHTTPChannel | 64 | protocol = TimeoutHTTPChannel |
---|
42 | | 65 | |
---|
| | 66 | if hasattr(config, "FORWARDED_FOR_HEADER"): |
---|
| | 67 | requestFactory = ProxyRequest |
---|
| | 68 | |
---|
43 | def __init__(self, path, *args, **kwargs): | 69 | def __init__(self, path, *args, **kwargs): |
---|
44 | root = RootResource() | 70 | root = RootResource() |
---|
45 | server.Site.__init__(self, root, *args, **kwargs) | 71 | server.Site.__init__(self, root, *args, **kwargs) |
---|