Broken when Reverse Proxy - CSRF_TRUSTED_ORIGINS Missing #851
Replies: 8 comments 2 replies
-
Thanks for the report. A few questions to help me understand what is going wrong:
|
Beta Was this translation helpful? Give feedback.
-
Nice work anymuster2, I can confirm this fixed the problem for me with Nginx. |
Beta Was this translation helpful? Give feedback.
-
For the record, adding
to my Nginx TLS proxy configured with
resolved the issue even without setting
so I just made the proxy play by those rules. |
Beta Was this translation helpful? Give feedback.
-
My NGINX block already had proxy_set_header, but it was set to $host instead of $http_host. Changing it to $http_host and removing the code changes also works. |
Beta Was this translation helpful? Give feedback.
-
Can confirm this issue. The error message below led me to here. I'm using HAProxy as reverse proxy. It took me hours to get it working. So I think it could be nice to share my solution with everybody. There's my HAProxy config file global
stats socket /var/run/api.sock user haproxy group haproxy mode 660 level admin expose-fd listeners
log stdout format raw local0 info
defaults
mode http
timeout client 10s
timeout connect 5s
timeout server 10s
timeout http-request 10s
default-server init-addr none
log global
resolvers docker_resolver
nameserver dns 127.0.0.11:53
frontend stats
bind *:8404
stats enable
stats uri /
stats refresh 10s
frontend myfrontend
bind :80
bind :443 ssl crt /usr/local/etc/haproxy/certs/
http-request redirect scheme https code 301 unless { ssl_fc }
use_backend %[req.hdr(Host),lower]
backend healthchecks.traefik.me
http-request del-header Origin
server healthchecks healthchecks:8000 check inter 10s resolvers docker_resolver This is my healthchecks version: '3.9'
networks:
healthchecks_net:
name: healthchecks_net
driver: bridge
haproxy_net:
external: true
# services
services:
healthchecks:
container_name: healthchecks
image: healthchecks/healthchecks:v2.8.1
restart: unless-stopped
environment:
- DEBUG=True
- DB=postgres
- DB_HOST=${DB_HOST}
- DB_NAME=${DB_NAME}
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
- REGISTRATION_OPEN=False
- ALLOWED_HOSTS=healthchecks.traefik.me
- SITE_ROOT=https://healthchecks.traefik.me
depends_on:
- healthchecks_database
networks:
- haproxy_net
- healthchecks_net
healthchecks_database:
container_name: healthchecks_database
image: postgres:15.0
restart: always
environment:
- PGDATA=/var/lib/postgresql/data
- POSTGRES_DB=${DB_NAME}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_USER=${DB_USER}
networks:
- healthchecks_net
volumes:
- ./data:/var/lib/postgresql/data In the example above, my healthchecks instance is reachable at What exactly fixed the problem?It's the line What it actually does?It deletes the Origin header before sending the request to the healthchecks container. Why?As shown in the screenshot, the reason given for the failure is my domain name not being present in the list of trusted domains. Yes, the Origin header value, is the domain name requested by users. So I needed to add my domain name to that list. Unfortunately, healthchecks docker container doesn't support yet setting the My workaround is to delete the origin header before forwarding the requests to the backend. ImprovementIt could be nice in next releases if @cuu508 could add support for In the end, thanks for this amazing project @cuu508. I just heard about this a couple of days ago and already like it. I also read one of your blog posts about your motivation and your journey running healthchecks.io. It's inspiring, keep it up ! |
Beta Was this translation helpful? Give feedback.
-
The Django docs say:
@theko2fi would you be able to go down the rabbit hole and figure out why the Host and Origin headers didn't match in your case? Here's my hunch. From Carlton Gibson's blog:
I think what might be happening, is:
If that's the case, the fix is to tell Haproxy to add a
The container image uses uwsgi, which by default checks the X-Forwarded-Proto header, and passes the value on to Django. Then Django knows if the request was secure or not, and the values of scheme+Host and Origin headers match. My current understanding is |
Beta Was this translation helpful? Give feedback.
-
Sure, I reversed the thing:
There's the configuration I used for that: frontend myfrontend
bind :80
bind :443 ssl crt /usr/local/etc/haproxy/certs/
#http-request redirect scheme https code 301 unless { ssl_fc }
use_backend %[req.hdr(Host),lower]
backend healthchecks.traefik.me
http-request set-header X-Forwarded-Proto https
server healthchecks healthchecks:8000 check inter 10s resolvers docker_resolver Then with that configuration, requests to So I can confirm, @cuu508 you're spot on. The problem is a mismatch between the scheme+Host and Origin headers. The solution is to tell HAProxy to pass the correct scheme to the healthchecks container. For people who come in future looking for a solution, this is the way to go: backend healthchecks.traefik.me
http-request set-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header X-Forwarded-Proto http unless { ssl_fc }
server healthchecks healthchecks:8000 check inter 10s resolvers docker_resolver Thanks ! |
Beta Was this translation helpful? Give feedback.
-
For anyone running healthchecks behnd Apache, adding "RequestHeader unset Origin" to the vhost solves the problem. |
Beta Was this translation helpful? Give feedback.
-
Seems like Django 4.x added mandatory origin verification - https://docs.djangoproject.com/en/4.2/ref/settings/#csrf-trusted-origins
Healthchecks broke for me with a reverse proxy with CSRF validation errors - I was unabble to register or login as a result. Adding and additional env option and adding the line
CSRF_TRUSTED_ORIGINS = os.getenv("CSRF_TRUSTED_ORIGINS").split(",")
tosettings.py
fixed the issue locally.Beta Was this translation helpful? Give feedback.
All reactions