mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
Change handling of headers that indicate SSL requests.
Instead of hardcoding X-Forwarded-Protocol and X-Forwarded-SSL, make the header and value configurable, with no default that would enable a client to spoof secure requests if the reverse proxy is not configured to strip the header used.
This commit is contained in:
parent
1a796ebbc6
commit
7e9f8b5b02
@ -336,6 +336,29 @@ int(value, 0) (0 means Python guesses the base, so values like "0",
|
||||
<p>This path should be writable by the process permissions set for Gunicorn
|
||||
workers. If not specified, Gunicorn will choose a system generated
|
||||
temporary directory.</p>
|
||||
</div>
|
||||
<div class="section" id="secure-scheme-headers">
|
||||
<h4><a class="toc-backref" href="#contents">secure_scheme_headers</a></h4>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">{
|
||||
"X-FORWARDED-PROTOCOL": "ssl",
|
||||
"X-FORWARDED-SSL": "on"
|
||||
}
|
||||
</tt></li>
|
||||
</ul>
|
||||
<p>A dictionary containing headers and values that the front-end proxy
|
||||
uses to indicate HTTPS requests. These tell gunicorn to set
|
||||
wsgi.url_scheme to "https", so your application can tell that the
|
||||
request is secure.</p>
|
||||
|
||||
<p>The dictionary should map upper-case header names to exact string
|
||||
values. The value comparisons are case-sensitive, unlike the header
|
||||
names, so make sure they're exactly what your front-end proxy sends
|
||||
when handling HTTPS requests.</p>
|
||||
|
||||
<p>It is important that your front-end proxy configuration ensures that
|
||||
the headers defined here can not be passed directly from the client.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="logging">
|
||||
@ -549,28 +572,29 @@ the just-exited Worker.</p>
|
||||
<li><a class="reference internal" href="#group" id="id27">group</a></li>
|
||||
<li><a class="reference internal" href="#umask" id="id28">umask</a></li>
|
||||
<li><a class="reference internal" href="#tmp-upload-dir" id="id29">tmp_upload_dir</a></li>
|
||||
<li><a class="reference internal" href="#secure-scheme-headers" id="id30">secure_scheme_headers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#logging" id="id30">Logging</a><ul>
|
||||
<li><a class="reference internal" href="#logfile" id="id31">logfile</a></li>
|
||||
<li><a class="reference internal" href="#loglevel" id="id32">loglevel</a></li>
|
||||
<li><a class="reference internal" href="#logconfig" id="id33">logconfig</a></li>
|
||||
<li><a class="reference internal" href="#logging" id="id31">Logging</a><ul>
|
||||
<li><a class="reference internal" href="#logfile" id="id32">logfile</a></li>
|
||||
<li><a class="reference internal" href="#loglevel" id="id33">loglevel</a></li>
|
||||
<li><a class="reference internal" href="#logconfig" id="id34">logconfig</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#process-naming" id="id34">Process Naming</a><ul>
|
||||
<li><a class="reference internal" href="#proc-name" id="id35">proc_name</a></li>
|
||||
<li><a class="reference internal" href="#default-proc-name" id="id36">default_proc_name</a></li>
|
||||
<li><a class="reference internal" href="#process-naming" id="id35">Process Naming</a><ul>
|
||||
<li><a class="reference internal" href="#proc-name" id="id36">proc_name</a></li>
|
||||
<li><a class="reference internal" href="#default-proc-name" id="id37">default_proc_name</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#server-hooks" id="id37">Server Hooks</a><ul>
|
||||
<li><a class="reference internal" href="#on-starting" id="id38">on_starting</a></li>
|
||||
<li><a class="reference internal" href="#when-ready" id="id39">when_ready</a></li>
|
||||
<li><a class="reference internal" href="#pre-fork" id="id40">pre_fork</a></li>
|
||||
<li><a class="reference internal" href="#post-fork" id="id41">post_fork</a></li>
|
||||
<li><a class="reference internal" href="#pre-exec" id="id42">pre_exec</a></li>
|
||||
<li><a class="reference internal" href="#pre-request" id="id43">pre_request</a></li>
|
||||
<li><a class="reference internal" href="#post-request" id="id44">post_request</a></li>
|
||||
<li><a class="reference internal" href="#worker-exit" id="id45">worker_exit</a></li>
|
||||
<li><a class="reference internal" href="#server-hooks" id="id38">Server Hooks</a><ul>
|
||||
<li><a class="reference internal" href="#on-starting" id="id39">on_starting</a></li>
|
||||
<li><a class="reference internal" href="#when-ready" id="id40">when_ready</a></li>
|
||||
<li><a class="reference internal" href="#pre-fork" id="id41">pre_fork</a></li>
|
||||
<li><a class="reference internal" href="#post-fork" id="id42">post_fork</a></li>
|
||||
<li><a class="reference internal" href="#pre-exec" id="id43">pre_exec</a></li>
|
||||
<li><a class="reference internal" href="#pre-request" id="id44">pre_request</a></li>
|
||||
<li><a class="reference internal" href="#post-request" id="id45">post_request</a></li>
|
||||
<li><a class="reference internal" href="#worker-exit" id="id46">worker_exit</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -179,6 +179,11 @@ def validate_bool(val):
|
||||
else:
|
||||
raise ValueError("Invalid boolean: %s" % val)
|
||||
|
||||
def validate_dict(val):
|
||||
if not isinstance(val, dict):
|
||||
raise TypeError("Value is not a dictionary: %s " % val)
|
||||
return val
|
||||
|
||||
def validate_pos_int(val):
|
||||
if not isinstance(val, (types.IntType, types.LongType)):
|
||||
val = int(val, 0)
|
||||
@ -522,6 +527,30 @@ class TmpUploadDir(Setting):
|
||||
temporary directory.
|
||||
"""
|
||||
|
||||
class SecureSchemeHeader(Setting):
|
||||
name = "secure_scheme_headers"
|
||||
section = "Server Mechanics"
|
||||
validator = validate_dict
|
||||
default = {
|
||||
"X-FORWARDED-PROTOCOL": "ssl",
|
||||
"X-FORWARDED-SSL": "on"
|
||||
}
|
||||
desc = """\
|
||||
|
||||
A dictionary containing headers and values that the front-end proxy
|
||||
uses to indicate HTTPS requests. These tell gunicorn to set
|
||||
wsgi.url_scheme to "https", so your application can tell that the
|
||||
request is secure.
|
||||
|
||||
The dictionary should map upper-case header names to exact string
|
||||
values. The value comparisons are case-sensitive, unlike the header
|
||||
names, so make sure they're exactly what your front-end proxy sends
|
||||
when handling HTTPS requests.
|
||||
|
||||
It is important that your front-end proxy configuration ensures that
|
||||
the headers defined here can not be passed directly from the client.
|
||||
"""
|
||||
|
||||
class Logfile(Setting):
|
||||
name = "logfile"
|
||||
section = "Logging"
|
||||
|
||||
@ -68,6 +68,8 @@ def create(req, sock, client, server, cfg):
|
||||
url_scheme = "http"
|
||||
script_name = os.environ.get("SCRIPT_NAME", "")
|
||||
|
||||
secure_headers = getattr(cfg, "secure_scheme_headers")
|
||||
|
||||
for hdr_name, hdr_value in req.headers:
|
||||
if hdr_name == "EXPECT":
|
||||
# handle expect
|
||||
@ -75,9 +77,8 @@ def create(req, sock, client, server, cfg):
|
||||
sock.send("HTTP/1.1 100 Continue\r\n\r\n")
|
||||
elif hdr_name == "X-FORWARDED-FOR":
|
||||
forward = hdr_value
|
||||
elif hdr_name == "X-FORWARDED-PROTOCOL" and hdr_value.lower() == "ssl":
|
||||
url_scheme = "https"
|
||||
elif hdr_name == "X-FORWARDED-SSL" and hdr_value.lower() == "on":
|
||||
elif (hdr_name.upper() in secure_headers and
|
||||
hdr_value == secure_headers[hdr_name.upper()]):
|
||||
url_scheme = "https"
|
||||
elif hdr_name == "HOST":
|
||||
server = hdr_value
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user