[Django] #33293: Wrong redirect behind reverse proxy

319 views
Skip to first unread message

Django

unread,
Nov 15, 2021, 5:34:56 AM11/15/21
to django-...@googlegroups.com
#33293: Wrong redirect behind reverse proxy
------------------------------------------+------------------------
Reporter: RodolpheGohard | Owner: nobody
Type: Uncategorized | Status: new
Component: contrib.admin | Version: 3.0
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
------------------------------------------+------------------------
I am running a small django app with django admin.
In fact, I only use django admin to edit a few models.

It works fine in local and behind a simple reverse proxy (without path
change), but now I have this rewrite rule that changes the path: (it's a
nginx ingress rewrite rule for Kubernetes)

path: /diagnosis-admin(/|$)(.*) => $2

Wich means, urls such as mydomain.com/diagnosis-admin redirect to
localhost/ (mind the path change).

When I try to access the admin at mydomain.com/diagnosis-admin/admin,
django tries to redirect to mydomain.com/admin/, which leads nowhere
because it falls on the proxy:

{{{

Request URL:
https://mydomain.com/diagnosis-admin/admin
Request Method:
GET
Status Code:
301
Remote Address:
138.21.17.33:3128
Referrer Policy:
strict-origin-when-cross-origin
Response Headers
content-length:
0
content-type:
text/html; charset=utf-8
date:
Tue, 19 Oct 2021 15:11:42 GMT
location:
/admin/
script_name:
/diagnosis-admin
strict-transport-security:
max-age=15724800; includeSubDomains
x-content-type-options:
nosniff
}}}

as you can see, django sends a "location: /admin/" redirect in the
response which causes the error


I had this problem with other applicative frameworks but could solve it
since they can interpret the FORWARDED_HOST, FORWARDED_PORT and
FORWARDED_PATH headers provided by the proxy.

Additionnal information:
I run django with "python manage.py runserver 0.0.0.0:8000" on a docker
container (running through GKE)

Everything is pretty standard, I ran the basic django project scafolding,
setup the database, auto migrated the models and that's about it. I can
provide additionnal files if needed


Additionnal information:
requirements.txt
{{{
requirements.txt:
asgiref==3.2.6
Django==3.0.4
psycopg2==2.8.4
pytz==2019.3
sqlparse==0.3.1
}}}


Dockerfile:
{{{
FROM python:3.6.10-alpine

COPY requirements.txt ./
RUN apk add --no-cache --virtual .build-deps \
ca-certificates gcc postgresql-dev linux-headers musl-dev \
libffi-dev jpeg-dev zlib-dev \
&& pip install -r requirements.txt
ENV PYTHONUNBUFFERED 1
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
ENTRYPOINT ["python", "manage.py"]
CMD ["runserver", "0.0.0.0:8000"]

}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/33293>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Nov 15, 2021, 7:20:42 AM11/15/21
to django-...@googlegroups.com
#33293: Wrong redirect behind reverse proxy
-------------------------------+--------------------------------------
Reporter: Rodolphe | Owner: nobody
Type: Uncategorized | Status: closed
Component: contrib.admin | Version: 3.0
Severity: Normal | Resolution: invalid

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Changes (by Mariusz Felisiak):

* status: new => closed
* resolution: => invalid


Comment:

Thanks for this report, however it looks like a support question 🤔 and
Trac is not a
[https://code.djangoproject.com/wiki/TicketClosingReasons/UseSupportChannels
support channel]. Have you tried to use
[https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-
USE_X_FORWARDED_HOST USE_X_FORWARDED_HOST] settings?


Please see TicketClosingReasons/UseSupportChannels for ways to get help
with Django usage.

--
Ticket URL: <https://code.djangoproject.com/ticket/33293#comment:1>

Django

unread,
Nov 16, 2021, 4:50:32 AM11/16/21
to django-...@googlegroups.com
#33293: Wrong redirect behind reverse proxy
-------------------------------+--------------------------------------
Reporter: Rodolphe | Owner: nobody
Type: Uncategorized | Status: closed
Component: contrib.admin | Version: 3.0
Severity: Normal | Resolution: invalid

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Comment (by Rodolphe):

Replying to [comment:1 Mariusz Felisiak]:


> Thanks for this report, however it looks like a support question 🤔 and
Trac is not a
[https://code.djangoproject.com/wiki/TicketClosingReasons/UseSupportChannels
support channel]. Have you tried to use
[https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-
USE_X_FORWARDED_HOST USE_X_FORWARDED_HOST] settings?
>
>
> Please see TicketClosingReasons/UseSupportChannels for ways to get help
with Django usage.

USE_X_FORWARDED_HOST doesn't work because it doesn't track the path
change. It tried support channels but they fail me. As I see it, this is
either a bug (django shouldn't do an absolute redirect), or a missing
feature (django should support a way to work behind reverse proxy with
path changes.)

--
Ticket URL: <https://code.djangoproject.com/ticket/33293#comment:2>

Django

unread,
Nov 16, 2021, 5:16:35 AM11/16/21
to django-...@googlegroups.com
#33293: Wrong redirect behind reverse proxy
-------------------------------+--------------------------------------
Reporter: Rodolphe | Owner: nobody
Type: Uncategorized | Status: closed
Component: contrib.admin | Version: 3.0
Severity: Normal | Resolution: invalid

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Comment (by Mariusz Felisiak):

> USE_X_FORWARDED_HOST doesn't work because it doesn't track the path
change. It tried support channels but they fail me. As I see it, this is
either a bug (django shouldn't do an absolute redirect), or a missing
feature (django should support a way to work behind reverse proxy with
path changes.)

You should be able to add a custom middleware with expected logic.

> It tried support channels but they fail me.

Please remember that folks on the support channels are volunteers who help
others in their spare time, you cannot expect an immediate help.

--
Ticket URL: <https://code.djangoproject.com/ticket/33293#comment:3>

Django

unread,
Nov 16, 2021, 10:11:31 AM11/16/21
to django-...@googlegroups.com
#33293: Wrong redirect behind reverse proxy
-------------------------------+--------------------------------------
Reporter: Rodolphe | Owner: nobody
Type: Uncategorized | Status: closed
Component: contrib.admin | Version: 3.0
Severity: Normal | Resolution: invalid

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Comment (by Keryn Knight):

Whilst this isn't a support channel, I'll add some possibly helpful
information below as a courtesy, and because who knows who else might
stumble across this in the future.

If your httpd (or whatever; could be a wsgi middleware etc) sets
`SCRIPT_NAME` and `PATH_INFO` to the correct values, ''and'' (maybe; it's
been a while) the setting
[https://docs.djangoproject.com/en/3.2/ref/settings/#force-script-name
FORCE_SCRIPT_NAME] to the prefix, anything that goes through
`reverse`/`resolve` in terms of generated URLs (for `Location` redirects
etc) should end up with the correct values.

e.g. `return HttpResponseRedirect(reverse('admin:index', ...))` would be
prefixed, but `return HttpResponseRedirect('/admin/')` would not.

For transparent reverse-proxying of all URLs AFAIK you'd need further co-
operation from either the WSGI publisher (e.g.
[https://docs.pylonsproject.org/projects/waitress/en/latest/reverse-
proxy.html?highlight=url_prefix#using-url-prefix-to-influence-script-name-
and-path-info See the waitress docs for their support]) or the fronting
httpd (e.g.
[https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypassreverse see
Apache's ProxyPassReverse])

Please note also this gentle reminder that you should ''not'' be using
runserver in anything ostensibly like "production" - you should be using
something designed for the purposes, such as
gunicorn/uwsgi/mod_wsgi/waitress/bjoern/meinheld.

--
Ticket URL: <https://code.djangoproject.com/ticket/33293#comment:4>

Reply all
Reply to author
Forward
0 new messages