Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#33293 closed Uncategorized (invalid)

Wrong redirect behind reverse proxy

Reported by: Rodolphe Owned by: nobody
Component: contrib.admin Version: 3.0
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

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"]

Change History (4)

comment:1 by Mariusz Felisiak, 3 years ago

Resolution: invalid
Status: newclosed

Thanks for this report, however it looks like a support question 🤔 and Trac is not a support channel. Have you tried to use USE_X_FORWARDED_HOST settings?

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

in reply to:  1 ; comment:2 by Rodolphe, 3 years ago

Replying to Mariusz Felisiak:

Thanks for this report, however it looks like a support question 🤔 and Trac is not a support channel. Have you tried to use 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.)

in reply to:  2 comment:3 by Mariusz Felisiak, 3 years ago

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.

comment:4 by Keryn Knight, 3 years ago

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 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. See the waitress docs for their support) or the fronting httpd (e.g. 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.

Note: See TracTickets for help on using tickets.
Back to Top