Permalink
Browse files

fix the correct remote address

The remote address should return the direct client addr not a forwarded
header.

This is a breaking change. The main problem with such changes is the way
the application or framework will handle the URL completion. Indeed most
of them are only expecting a TCP socket.

fix #633
  • Loading branch information...
1 parent 776f315 commit c4873681299212d6082cd9902740eef18c2f14f1 @benoitc committed Dec 27, 2013
Showing with 14 additions and 52 deletions.
  1. +1 −14 gunicorn/config.py
  2. +13 −38 gunicorn/http/wsgi.py
View
@@ -914,19 +914,6 @@ class SecureSchemeHeader(Setting):
"""
-class XForwardedFor(Setting):
- name = "x_forwarded_for_header"
- section = "Server Mechanics"
- cli = ["--x-forwarded-for-hdr"]
- meta = "STRING"
- validator = validate_string
- default = 'X-FORWARDED-FOR'
- desc = """\
- Set the X-Forwarded-For header that identify the originating IP
- address of the client connection to gunicorn via a proxy.
- """
-
-
class ForwardedAllowIPS(Setting):
name = "forwarded_allow_ips"
section = "Server Mechanics"
@@ -935,7 +922,7 @@ class ForwardedAllowIPS(Setting):
validator = validate_string_to_list
default = "127.0.0.1"
desc = """\
- Front-end's IPs from which allowed to handle X-Forwarded-* headers.
+ Front-end's IPs from which allowed to handle set secure headers.
(comma separate).
Set to "*" to disable checking of Front-end IPs (useful for setups
View
@@ -80,29 +80,22 @@ def create(req, sock, client, server, cfg):
environ = default_environ(req, sock, cfg)
- # authors should be aware that REMOTE_HOST and REMOTE_ADDR
- # may not qualify the remote addr:
- # http://www.ietf.org/rfc/rfc3875
- forward = client or "127.0.0.1"
url_scheme = "https" if cfg.is_ssl else "http"
script_name = os.environ.get("SCRIPT_NAME", "")
secure_headers = cfg.secure_scheme_headers
- x_forwarded_for_header = cfg.x_forwarded_for_header
- if '*' not in cfg.forwarded_allow_ips and client\
- and client[0] not in cfg.forwarded_allow_ips:
- x_forwarded_for_header = None
- secure_headers = {}
+ if client and not isinstance(client, string_types):
+ if ('*' not in cfg.forwarded_allow_ips
+ and client[0] not in cfg.forwarded_allow_ips):
+ secure_headers = {}
for hdr_name, hdr_value in req.headers:
if hdr_name == "EXPECT":
# handle expect
if hdr_value.lower() == "100-continue":
sock.send(b"HTTP/1.1 100 Continue\r\n\r\n")
- elif x_forwarded_for_header and hdr_name == x_forwarded_for_header:
- forward = hdr_value
- elif secure_headers and (hdr_name.upper() in secure_headers and
- hdr_value == secure_headers[hdr_name.upper()]):
+ elif secure_headers and (hdr_name in secure_headers and
+ hdr_value == secure_headers[hdr_name]):
url_scheme = "https"
elif hdr_name == "HOST":
server = hdr_value
@@ -122,32 +115,14 @@ def create(req, sock, client, server, cfg):
environ['wsgi.url_scheme'] = url_scheme
- if isinstance(forward, string_types):
- # we only took the last one
- # http://en.wikipedia.org/wiki/X-Forwarded-For
- if forward.find(",") >= 0:
- forward = forward.rsplit(",", 1)[1].strip()
-
- # find host and port on ipv6 address
- if '[' in forward and ']' in forward:
- host = forward.split(']')[0][1:].lower()
- elif ":" in forward and forward.count(":") == 1:
- host = forward.split(":")[0].lower()
- else:
- host = forward
-
- forward = forward.split(']')[-1]
- if ":" in forward and forward.count(":") == 1:
- port = forward.split(':', 1)[1]
- else:
- port = 80
-
- remote = (host, port)
+ # authors should be aware that REMOTE_HOST and REMOTE_ADDR
+ # may not qualify the remote addr:
+ # http://www.ietf.org/rfc/rfc3875
+ if isinstance(client, string_types):
+ environ['REMOTE_ADDR'] = client
else:
- remote = forward
-
- environ['REMOTE_ADDR'] = remote[0]
- environ['REMOTE_PORT'] = str(remote[1])
+ environ['REMOTE_ADDR'] = client[0]
+ environ['REMOTE_PORT'] = str(client[1])
if isinstance(server, string_types):
server = server.split(":")

0 comments on commit c487368

Please sign in to comment.