diff options
author | Guang Yee <guang.yee@hpe.com> | 2016-09-07 17:37:33 -0700 |
---|---|---|
committer | Guang Yee <guang.yee@hpe.com> | 2016-09-08 10:45:42 -0700 |
commit | df01234bd864062a1dddd071b1d265153867f4b1 (patch) | |
tree | cde0283ef0e478ec9173faab63b5a02a030a61eb | |
parent | 5b5acf659656f550821a342bcefc6015fb0ec7b4 (diff) | |
download | oslo-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.py | 8 | ||||
-rw-r--r-- | oslo_middleware/tests/test_http_proxy_to_wsgi.py | 23 |
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): |