#Forbidden 403

9 messages · Page 1 of 1 (latest)

white dawn
#

Hi, first time attempting to deploy on the cloud and in “Production”. My application was working correctly until I attempted to implement HTTPS. I was able to access the admin panel without issue make and make one post, now I am unable access the admin panel.
I was browsing other similar issues and most of the fixes consisted of adding CSRF_TRUSTED_ORIGINS.
Not in my case.

I think I am stuck with my novice understanding of the security of HTTPS: The POST request from nginx doesn’t have the correct headers to satisfy Djangos requirements to access the resources being requested?

I have added my IP/Domain to the CSRF list, rebuilt the images and cleared the browsing history.

I am out of ideas on what I need to try next.

I have a standard html front end.
Cookie is present when inspecting: csrftoken l5nlxaw### www.django-blog-jb.com Lax

Forbidden (403)
CSRF verification failed. Request aborted.
Origin checking failed -

#
ALLOWED_HOSTS = [
        'www.django-blog-jb.com',
        'django-blog-jb.com',
        '3.15.27.43,'
        'localhost',
]

CSRF_TRUSTED_ORIGINS = [
    "https://www.django-blog-jb.com",
    "https://django-blog-jb.com",
    "https://3.15.27.43",
]

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
SECURE_SSL_REDIRECT = True
#

standard HTML Front End,

#

Headers Tab Dev tools output:

https://www.django-blog-jb.com/admin/login/?next=/admin/
Request Method:
POST
Status Code:
403 Forbidden
Remote Address:
3.15.27.43:443
Referrer Policy:
same-origin
connection:
keep-alive
content-length:
2563
content-type:
text/html; charset=utf-8
cross-origin-opener-policy:
same-origin
date:
Wed, 22 Jan 2025 12:04:20 GMT
referrer-policy:
same-origin
server:
nginx/1.27.3
x-content-type-options:
nosniff
x-frame-options:
DENY
accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
accept-encoding:
gzip, deflate, br, zstd
accept-language:
en-US,en;q=0.9
cache-control:
max-age=0
connection:
keep-alive
content-length:
141
content-type:
application/x-www-form-urlencoded
cookie:
csrftoken=UppKxZO0rQ9via72O3w5QDvoz5fdVuxp
host:
www.django-blog-jb.com
origin:
https://www.django-blog-jb.com
referer:
https://www.django-blog-jb.com/admin/login/?next=/admin/
sec-ch-ua:
"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
sec-ch-ua-mobile:
?0
sec-ch-ua-platform:
"macOS"
sec-fetch-dest:
document
sec-fetch-mode:
navigate
sec-fetch-site:
same-origin
sec-fetch-user:
?1
upgrade-insecure-requests:
1
user-agent:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36```
coarse nexus
#

I don't see anything obviously wrong. I seem to recall having this problem as well, and making my two POST endpoints @csrf_exempt 😦

white dawn
#

I have NGINX configured as a reverse proxy and gunicorn as the application server. Is the issue with gunicorn and Django accepting the post request? I am having a hard time understanding what the actual problem is. Here are some web and nginx logs

my_blog-nginx-1  | 172.232.133.233 - - [23/Jan/2025:13:31:27 +0000] "M" 400 157 "-" "-" "-"
my_blog-nginx-1  | 5.181.190.248 - - [23/Jan/2025:13:37:59 +0000] "GET / HTTP/1.1" 301 169 "-" "-" "-"
my_blog-nginx-1  | 5.181.190.248 - - [23/Jan/2025:13:38:01 +0000] "GET / HTTP/1.1" 400 59159 "http://3.15.27.43:80/" "-" "-"
my_blog-nginx-1  | 76.34.237.147 - - [23/Jan/2025:14:32:14 +0000] "GET / HTTP/1.1" 200 4468 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
my_blog-nginx-1  | 76.34.237.147 - - [23/Jan/2025:14:32:23 +0000] "GET /admin/ HTTP/1.1" 302 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
my_blog-nginx-1  | 76.34.237.147 - - [23/Jan/2025:14:32:23 +0000] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 4160 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
my_blog-nginx-1  | 76.34.237.147 - - [23/Jan/2025:14:32:26 +0000] "POST /admin/login/?next=/admin/ HTTP/1.1" 403 2563 "https://www.django-blog-jb.com/admin/login/?next=/admin/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"

#
my_blog-web-1    |     host = request.get_host()
my_blog-web-1    |            ^^^^^^^^^^^^^^^^^^
my_blog-web-1    |   File "/usr/local/lib/python3.11/site-packages/django/http/request.py", line 151, in get_host
my_blog-web-1    |     raise DisallowedHost(msg)
my_blog-web-1    | django.core.exceptions.DisallowedHost: Invalid HTTP_HOST header: '3.15.27.43'. You may need to add '3.15.27.43' to ALLOWED_HOSTS.
my_blog-web-1    | Bad Request: /
my_blog-web-1    | Invalid HTTP_HOST header: '3.15.27.43'. You may need to add '3.15.27.43' to ALLOWED_HOSTS.
my_blog-web-1    | Traceback (most recent call last):```
coarse nexus
#

maybe you need to ensure that the proxy is passing through the X-CSRFToken header

white dawn
#

nginx config:


# Define the limit request zone at the HTTP level
limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;

server {
    listen 80;
    server_name www.django-blog-jb.com django-blog-jb.com;

    # Redirect HTTP traffic to HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name www.django-blog-jb.com django-blog-jb.com;

    # SSL certificates
    ssl_certificate /etc/letsencrypt/live/www.django-blog-jb.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.django-blog-jb.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # Serve static files
    location /static/ {
       alias /app/staticfiles/;
       access_log /var/log/nginx/static_access.log;
       error_log /var/log/nginx/static_error.log debug;
    }

    # Proxy pass to the Gunicorn app
    location / {
        proxy_pass http://web:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Apply rate limiting to all requests
        limit_req zone=one burst=10 nodelay;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

   # Block known malicious traffic
    location ~* (\.env|/remote/login) {
        return 403;
    }
}```