summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2019-07-14 15:16:50 -0500
committerMichael Merickel <michael@merickel.org>2019-07-14 15:16:50 -0500
commit9695c5d9a0eae818a4e9c2e5becb826c24e4533d (patch)
treebbc05c78c1a94b7ec936c142816b56f077fe286b
parent01f7abef33241ccfeed1ae1c707a59ddd8d8b726 (diff)
downloadwaitress-9695c5d9a0eae818a4e9c2e5becb826c24e4533d.tar.gz
log the header value
-rw-r--r--waitress/adjustments.py7
-rw-r--r--waitress/proxy_headers.py104
-rw-r--r--waitress/utilities.py24
3 files changed, 78 insertions, 57 deletions
diff --git a/waitress/adjustments.py b/waitress/adjustments.py
index 5c1879b..f33c570 100644
--- a/waitress/adjustments.py
+++ b/waitress/adjustments.py
@@ -17,7 +17,7 @@ import getopt
import socket
import warnings
-from .utilities import PROXY_HEADERS
+from .proxy_headers import PROXY_HEADERS
from .compat import (
PY2,
WIN,
@@ -27,7 +27,10 @@ from .compat import (
truthy = frozenset(('t', 'true', 'y', 'yes', 'on', '1'))
-KNOWN_PROXY_HEADERS = {header.lower().replace('_', '-') for header in PROXY_HEADERS}
+KNOWN_PROXY_HEADERS = frozenset(
+ header.lower().replace('_', '-')
+ for header in PROXY_HEADERS
+)
def asbool(s):
""" Return the boolean value ``True`` if the case-lowered value of string
diff --git a/waitress/proxy_headers.py b/waitress/proxy_headers.py
index a788dfc..501dc2b 100644
--- a/waitress/proxy_headers.py
+++ b/waitress/proxy_headers.py
@@ -4,22 +4,23 @@ from .utilities import logger, undquote, BadRequest
PROXY_HEADERS = frozenset({
- 'HTTP_X_FORWARDED_FOR',
- 'HTTP_X_FORWARDED_HOST',
- 'HTTP_X_FORWARDED_PROTO',
- 'HTTP_X_FORWARDED_PORT',
- 'HTTP_X_FORWARDED_BY',
- 'HTTP_FORWARDED',
+ 'X_FORWARDED_FOR',
+ 'X_FORWARDED_HOST',
+ 'X_FORWARDED_PROTO',
+ 'X_FORWARDED_PORT',
+ 'X_FORWARDED_BY',
+ 'FORWARDED',
})
Forwarded = namedtuple('Forwarded', ['by', 'for_', 'host', 'proto'])
class MalformedProxyHeader(Exception):
- def __init__(self, header, reason):
+ def __init__(self, header, reason, value):
self.header = header
self.reason = reason
- Exception.__init__(self, header, reason)
+ self.value = value
+ super(MalformedProxyHeader, self).__init__(header, reason, value)
def proxy_headers_middleware(
@@ -31,7 +32,7 @@ def proxy_headers_middleware(
log_untrusted=False,
logger=logger,
):
- def consume_proxy_headers(environ, start_response):
+ def translate_proxy_headers(environ, start_response):
untrusted_headers = PROXY_HEADERS
remote_peer = environ['REMOTE_ADDR']
if trusted_proxy == '*' or remote_peer == trusted_proxy:
@@ -43,8 +44,9 @@ def proxy_headers_middleware(
logger=logger,
)
except MalformedProxyHeader as ex:
- logger.warn('malformed proxy header "%s" from "%s": %s',
- ex.header, remote_peer, ex.reason)
+ logger.warning(
+ 'Malformed proxy header "%s" from "%s": %s value: %s',
+ ex.header, remote_peer, ex.reason, ex.value)
error = BadRequest('Header "{0}" malformed.'.format(ex.header))
return error.wsgi_response(environ, start_response)
@@ -58,7 +60,7 @@ def proxy_headers_middleware(
)
return app(environ, start_response)
- return consume_proxy_headers
+ return translate_proxy_headers
def parse_proxy_headers(
@@ -75,11 +77,9 @@ def parse_proxy_headers(
client_addr = None
untrusted_headers = set(PROXY_HEADERS)
- def warn_unspecified_behavior(header):
- logger.warning(
- "Found multiple values in \"%s\", this has unspecified behaviour. "
- "Ignoring header value.",
- header,
+ def raise_for_multiple_values():
+ raise ValueError(
+ 'Unspecified behavior for multiple values found in header',
)
if (
@@ -107,9 +107,13 @@ def parse_proxy_headers(
forwarded_for = forwarded_for[-trusted_proxy_count:]
client_addr = forwarded_for[0]
- untrusted_headers.remove("HTTP_X_FORWARDED_FOR")
+ untrusted_headers.remove("X_FORWARDED_FOR")
except Exception as ex:
- raise MalformedProxyHeader('X-Forwarded-For', str(ex))
+ raise MalformedProxyHeader(
+ "X-Forwarded-For",
+ str(ex),
+ environ['HTTP_X_FORWARDED_FOR'],
+ )
if (
"x-forwarded-host" in trusted_proxy_headers
@@ -126,40 +130,48 @@ def parse_proxy_headers(
forwarded_host_multiple = forwarded_host_multiple[-trusted_proxy_count:]
forwarded_host = forwarded_host_multiple[0]
- untrusted_headers.remove("HTTP_X_FORWARDED_HOST")
+ untrusted_headers.remove("X_FORWARDED_HOST")
except Exception as ex:
- raise MalformedProxyHeader('X-Forwarded-Host', str(ex))
+ raise MalformedProxyHeader(
+ "X-Forwarded-Host",
+ str(ex),
+ environ['HTTP_X_FORWARDED_HOST'],
+ )
if "x-forwarded-proto" in trusted_proxy_headers:
try:
forwarded_proto = undquote(environ.get("HTTP_X_FORWARDED_PROTO", ""))
- untrusted_headers.remove("HTTP_X_FORWARDED_PROTO")
+ if ',' in forwarded_proto:
+ raise_for_multiple_values()
+ untrusted_headers.remove("X_FORWARDED_PROTO")
except Exception as ex:
- raise MalformedProxyHeader('X-Forwarded-Proto', str(ex))
-
- if "," in forwarded_proto:
- forwarded_proto = ""
- warn_unspecified_behavior("X-Forwarded-Proto")
+ raise MalformedProxyHeader(
+ "X-Forwarded-Proto",
+ str(ex),
+ environ['HTTP_X_FORWARDED_PROTO'],
+ )
if "x-forwarded-port" in trusted_proxy_headers:
try:
forwarded_port = undquote(environ.get("HTTP_X_FORWARDED_PORT", ""))
- untrusted_headers.remove("HTTP_X_FORWARDED_PORT")
+ if ',' in forwarded_port:
+ raise_for_multiple_values()
+ untrusted_headers.remove("X_FORWARDED_PORT")
except Exception as ex:
- raise MalformedProxyHeader('X-Forwarded-Port', str(ex))
-
- if "," in forwarded_port:
- forwarded_port = ""
- warn_unspecified_behavior("X-Forwarded-Port")
+ raise MalformedProxyHeader(
+ "X-Forwarded-Port",
+ str(ex),
+ environ['HTTP_X_FORWARDED_PORT'],
+ )
if "x-forwarded-by" in trusted_proxy_headers:
# Waitress itself does not use X-Forwarded-By, but we can not
# remove it so it can get set in the environ
- untrusted_headers.remove("HTTP_X_FORWARDED_BY")
+ untrusted_headers.remove("X_FORWARDED_BY")
if "forwarded" in trusted_proxy_headers:
forwarded = environ.get("HTTP_FORWARDED", None)
- untrusted_headers = PROXY_HEADERS - {"HTTP_FORWARDED"}
+ untrusted_headers = PROXY_HEADERS - {"FORWARDED"}
# If the Forwarded header exists, it gets priority
if forwarded:
@@ -182,13 +194,13 @@ def parse_proxy_headers(
token, equals, value = pair.partition("=")
if equals != "=":
- raise ValueError('invalid forwarded-pair missing "="')
+ raise ValueError('Invalid forwarded-pair missing "="')
if token.strip() != token:
- raise ValueError('token may not be surrounded by whitespace')
+ raise ValueError('Token may not be surrounded by whitespace')
if value.strip() != value:
- raise ValueError('value may not be surrounded by whitespace')
+ raise ValueError('Value may not be surrounded by whitespace')
if token == "by":
forwarded_by = undquote(value)
@@ -211,7 +223,9 @@ def parse_proxy_headers(
)
)
except Exception as ex:
- raise MalformedProxyHeader('Forwarded', str(ex))
+ raise MalformedProxyHeader(
+ "Forwarded", str(ex), environ['HTTP_FORWARDED'],
+ )
proxies = proxies[-trusted_proxy_count:]
@@ -238,10 +252,11 @@ def parse_proxy_headers(
if forwarded_proto:
forwarded_proto = forwarded_proto.lower()
- if forwarded_proto not in {'http', 'https'}:
+ if forwarded_proto not in {"http", "https"}:
raise MalformedProxyHeader(
- 'Forwarded Proto=' if forwarded else 'X-Forwarded-Proto',
- 'unsupported proto value'
+ "Forwarded Proto=" if forwarded else "X-Forwarded-Proto",
+ "unsupported proto value",
+ forwarded_proto,
)
# Set the URL scheme to the proxy provided proto
@@ -304,6 +319,7 @@ def parse_proxy_headers(
environ["REMOTE_PORT"] = port.strip()
else:
environ["REMOTE_ADDR"] = strip_brackets(client_addr.strip())
+ environ["REMOTE_HOST"] = environ["REMOTE_ADDR"]
return untrusted_headers
@@ -320,12 +336,12 @@ def clear_untrusted_headers(
untrusted_headers_removed = [
header
for header in untrusted_headers
- if environ.pop(header, False) is not False
+ if environ.pop('HTTP_' + header, False) is not False
]
if log_warning and untrusted_headers_removed:
untrusted_headers_removed = [
- "-".join(x.capitalize() for x in header.lstrip('HTTP_').split("_"))
+ "-".join(x.capitalize() for x in header.split("_"))
for header in untrusted_headers_removed
]
logger.warning(
diff --git a/waitress/utilities.py b/waitress/utilities.py
index d32affc..f06bdc9 100644
--- a/waitress/utilities.py
+++ b/waitress/utilities.py
@@ -109,17 +109,19 @@ def unpack_rfc822(m):
# rfc850 format
rfc850_date = join(
- [concat(long_day_reg, ','),
- join(
- [group('[0-9][0-9]?'),
- months_reg,
- group('[0-9]+')
- ],
- '-'
- ),
- hms_reg,
- 'gmt'
- ],
+ [
+ concat(long_day_reg, ','),
+ join(
+ [
+ group('[0-9][0-9]?'),
+ months_reg,
+ group('[0-9]+')
+ ],
+ '-'
+ ),
+ hms_reg,
+ 'gmt'
+ ],
' '
)