summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuang Yee <guang.yee@hpe.com>2016-09-07 17:37:33 -0700
committerGuang Yee <guang.yee@hpe.com>2016-09-08 10:45:42 -0700
commitdf01234bd864062a1dddd071b1d265153867f4b1 (patch)
treecde0283ef0e478ec9173faab63b5a02a030a61eb
parent5b5acf659656f550821a342bcefc6015fb0ec7b4 (diff)
downloadoslo-middleware-df01234bd864062a1dddd071b1d265153867f4b1.tar.gz
make sure we handle the forwarded for headers
The X-Forwarded-For header or the "for=" component in the Forwarded header (per RFC 7239) is essential for applications to keep track of the originating peer IP. CADF auditing, for example, is relying on REMOTE_ADDR to accurating keeping track of the real client address. If either headers are present, the REMOTE_ADDR WSGI request environment variable will be replaced by the forwarded for address. The Forwarded header have precedence over the X-Forwarded-For header. Change-Id: Ib690e3274cd00d8cfa8a15d341ac433555495ce6
-rw-r--r--oslo_middleware/http_proxy_to_wsgi.py8
-rw-r--r--oslo_middleware/tests/test_http_proxy_to_wsgi.py23
2 files changed, 31 insertions, 0 deletions
diff --git a/oslo_middleware/http_proxy_to_wsgi.py b/oslo_middleware/http_proxy_to_wsgi.py
index 84bc32b..4d68bcf 100644
--- a/oslo_middleware/http_proxy_to_wsgi.py
+++ b/oslo_middleware/http_proxy_to_wsgi.py
@@ -71,6 +71,10 @@ class HTTPProxyToWSGI(base.ConfigurableMiddleware):
if forwarded_host:
req.environ['HTTP_HOST'] = forwarded_host
+ forwarded_for = proxy.get("for")
+ if forwarded_for:
+ req.environ['REMOTE_ADDR'] = forwarded_for
+
else:
# World before RFC7239
forwarded_proto = req.environ.get("HTTP_X_FORWARDED_PROTO")
@@ -81,6 +85,10 @@ class HTTPProxyToWSGI(base.ConfigurableMiddleware):
if forwarded_host:
req.environ['HTTP_HOST'] = forwarded_host
+ forwarded_for = req.environ.get("HTTP_X_FORWARDED_FOR")
+ if forwarded_for:
+ req.environ['REMOTE_ADDR'] = forwarded_for
+
v = req.environ.get("HTTP_X_FORWARDED_PREFIX")
if v:
req.environ['SCRIPT_NAME'] = v + req.environ['SCRIPT_NAME']
diff --git a/oslo_middleware/tests/test_http_proxy_to_wsgi.py b/oslo_middleware/tests/test_http_proxy_to_wsgi.py
index 26baa77..1554ece 100644
--- a/oslo_middleware/tests/test_http_proxy_to_wsgi.py
+++ b/oslo_middleware/tests/test_http_proxy_to_wsgi.py
@@ -103,6 +103,29 @@ class TestHTTPProxyToWSGI(test_base.BaseTestCase):
response = self.request.get_response(self.middleware)
self.assertEqual(b"https://example.com:8043/bla", response.body)
+ def test_forwarded_for_headers(self):
+ @webob.dec.wsgify()
+ def fake_app(req):
+ return req.environ['REMOTE_ADDR']
+
+ self.middleware = http_proxy_to_wsgi.HTTPProxyToWSGIMiddleware(
+ fake_app)
+ forwarded_for_addr = '1.2.3.4'
+ forwarded_addr = '8.8.8.8'
+
+ # If both X-Forwarded-For and Fowarded headers are present, it should
+ # use the Forwarded header and ignore the X-Forwarded-For header.
+ self.request.headers['Forwarded'] = (
+ "for=%s;proto=https;host=example.com:8043" % (forwarded_addr))
+ self.request.headers['X-Forwarded-For'] = forwarded_for_addr
+ response = self.request.get_response(self.middleware)
+ self.assertEqual(forwarded_addr.encode(), response.body)
+
+ # Now if only X-Forwarded-For header is present, it should be used.
+ del self.request.headers['Forwarded']
+ response = self.request.get_response(self.middleware)
+ self.assertEqual(forwarded_for_addr.encode(), response.body)
+
class TestHTTPProxyToWSGIDisabled(test_base.BaseTestCase):