{{{
class ProtectAdminMiddleware(object):
def process_request(self, request):
if request.path.startswith("/admin") and
request.META["HTTP_X_FORWARDED_PORT"] != "444":
raise Http404
}}}
When turning on USE_X_FORWARDED_HOST, the code in HttpRequest.get_host
does not take port into account:
{{{
[...]
if settings.USE_X_FORWARDED_HOST and (
'HTTP_X_FORWARDED_HOST' in self.META):
host = self.META['HTTP_X_FORWARDED_HOST']
elif 'HTTP_HOST' in self.META:
host = self.META['HTTP_HOST']
[...]
}}}
Because of this, at least two things in the admin interface on port 444
don't function correctly; the CSRF token breaks saying there is a problem
between referrer on 444 and token on 443 and you can't login. Also,
redirects from say "/admin" on port 444 redirect to "/admin/" on 443
instead of staying on 444. That's just what I was able to reach with
logins broken.
I monkey-patched HttpRequest.get_host to add support for X-Forwarded-Port
when USE_X_FORWARDED_HOST is specified and it appears to have corrected
these issues:
{{{
[...]
if settings.USE_X_FORWARDED_HOST and (
'HTTP_X_FORWARDED_HOST' in self.META):
host = self.META['HTTP_X_FORWARDED_HOST']
if 'HTTP_X_FORWARDED_PORT' in self.META:
server_port = str(self.META['HTTP_X_FORWARDED_PORT'])
if server_port != (self.is_secure() and '443' or '80'):
host = '%s:%s' % (host, server_port)
elif 'HTTP_HOST' in self.META:
host = self.META['HTTP_HOST']
[...]
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/19517>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_tests: => 0
* easy: 0 => 1
* needs_docs: => 0
* type: Uncategorized => Bug
* stage: Unreviewed => Accepted
--
Ticket URL: <https://code.djangoproject.com/ticket/19517#comment:1>
Comment (by hirokiky):
I found pull-request for this ticket here
https://github.com/django/django/pull/619 written by mattrobenolt.
--
Ticket URL: <https://code.djangoproject.com/ticket/19517#comment:2>
* has_patch: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/19517#comment:3>
* cc: hirokiky@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/19517#comment:4>
* status: new => closed
* resolution: => wontfix
Comment:
I'm rejecting this after a discussion during the 2013 sprint:
- The use case of handing a SSL request with a load balancer is handled
already by the `SECURE_PROXY_SSL_HEADER` setting.
- `HTTP_X_FORWARDED_PORT` is not a standard header and this ticket hasn't
produced compelling evidence that Django is breaking any spec.
- Adding a new setting pair of `HTTP_X_FORWARDED_PORT` and
`USE_X_FORWARDED_PORT` just for this edge case is a no-go, too.
In other words, the issue is an edge case that can be solved by a custom
middleware in your application (e.g. by setting `HTTP_HOST`).
--
Ticket URL: <https://code.djangoproject.com/ticket/19517#comment:5>
Comment (by mattlong):
To be fair, `X-Forwarded-Host` is also not in any spec or standard that I
can find. It's added automatically by Apache's mod_proxy, but that seems
to be the only place. Having special handling for one custom header
without the other seems incorrect as there is currently no way (besides
middleware to change `HTTP_HOST` as jezdez suggests) to accurately get the
original request's host/port combo as the OP describes.
It seems reasonable to me to expect that `HTTP_X_FORWARDED_PORT` would
also be respected by HttpRequest.get_host if `USE_X_FORWARDED_HOST` is
enabled. Currently, I will also be opting to monkey patch get_host rather
than add the (admittedly small) overhead of an additional middleware on
all requests.
--
Ticket URL: <https://code.djangoproject.com/ticket/19517#comment:6>
* cc: matt@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/19517#comment:7>
Comment (by collinanderson):
There's a new `Forwarded:` header that standardizes `for`, `proto`,
`host`, and `by`, but not `port`. http://tools.ietf.org/html/rfc7239
If you want to discuss it further, please use the
https://groups.google.com/d/forum/django-developers mailing list, as this
is a closed ticket.
--
Ticket URL: <https://code.djangoproject.com/ticket/19517#comment:8>
Comment (by hgdeoro):
I have the same problem with bad redirects on the testing environment
(where the non-standar 8443 port is used). I found a workaround for Nginx.
Just add:
{{{
error_page 497 https://$host:8443$request_uri;
}}}
With that configuration, instead of the error message `The plain HTTP
request was sent to HTTPS port`, your browser receives a redirect to the
real URL. This is NOT a solution, this introduces an extra redirect, but
worked for me (and it's better than modifying the aplication, since this
is a problem I have in the testing environment only).
--
Ticket URL: <https://code.djangoproject.com/ticket/19517#comment:9>