I am desperate.
I have a https server that redirects traffic to my local https server.
My university runs a reverse proxy that forwards the requests my nginx:
The local https server is only visible from the vpn. They do that so that I do not have to care about the keys management and I can just plug some generic ones.
When I on the VPN the external server works as expected but when I am out of the VPN the external server returns CSRF token missing or incorrect.. Sometimes i receive CSRF cookie not set.
I have checked basically everything and read all the CSRF verification failed. Request aborted. posts here.
On the form I try to submit I can see csrfmiddlewaretoken <input type='hidden' name='csrfmiddlewaretoken' value="jdwjwjefjwdjqwølksqøwkop2j3ofje" />
The url in the external server is (anonymized):
https://project.uni.edu/
The url of the internal server (anonymized):
https://project_internal.uni.edux/
The configuration of the nginx:
server {
listen 443 ssl;
server_name project.uni.edu localhost;
ssl_certificate /code/staticfiles/cert/project_name.pem;
ssl_certificate_key /code/staticfiles/cert/project_name_key.pem;
location / {
proxy_pass http://web:8000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
}
location /static/ {
alias /code/staticfiles/;
}
location /media/ {
alias /code/mediafiles/;
}
}
My settings in the django file are:
CSRF_TRUSTED_ORIGINS = ["https://project.uni.edu/","https://project_internal.uni.edux/"]
# SESSION_COOKIE_SECURE= True
CSRF_COOKIE_HTTPONLY = False
SESSION_COOKIE_DOMAIN= "project_internal.uni.edux"
I have no idea what's happening. Thanks
Related
I'm trying to test a deployment config for a Django setup that works fine in development mode.
I have name-based routing via Nginx's ssl_preread module on a load balancer, and SSL terminates at another Nginx instance on the server itself where the requests are proxied to uwsgi by socket.
server {
server_name dev.domain.net;
listen 80 proxy_protocol;
listen [::]:80 proxy_protocol;
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name dev.domain.net;
listen 443 ssl;
listen [::]:443 ssl;
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/website.sock;
}
location /favicon.ico {
access_log off; log_not_found off;
}
}
I have uwsgi set to log %(host) and %(referer), they match in the logs.
In my uwsgi_params I'm passing $host and $referer like so, since I'm using name-based routing I pick up the $server_name variable that triggered the Nginx response...
uwsgi_param HTTP_REFERER $server_name;
uwsgi_param HTTP_HOST $host;
Adding (or taking away) protocols and ports to these makes no difference. Taking them away predictably generates a Django ALLOWED_HOSTS debug error.
I've confirmed that my ALLOWED_HOSTS includes the $host. I've tried adding CSRF_TRUSTED_ORIGINS for the same $host variable. I've tried setting CSRF_COOKIE_DOMAIN for the same $host variable. I have CSRF_COOKIE_SECURE set to True per the docs recommendation.
No matter what combination of the above settings are used, I get:
Referer checking failed - Referer is malformed. on all POST requests.
Short answer: don't use the uwsgi unix socket, but rather use http-socket and send the proxy request to localhost over unencrypted http (in uwsgi ini file):
http-socket = 127.0.0.1:8001
In nginx, get rid of uwsgi proxy params and simply proxy_pass with proxy_protocol headers enabled:
server {
server_name dev.domain.net;
listen 443 ssl proxy_protocol;
listen [::]:443 ssl proxy_protocol;
location / {
proxy_pass http://127.0.0.1:8001;
}
location /favicon.ico {
access_log off; log_not_found off;
}
}
At that point you can enable all of the recommended deployment settings in the Django docs, explicitly declare your ALLOWED_HOSTS and everything works fine.
These are a quite silly series of hoops with no apparent correct set of answers, especially considering referers are client headers that are easily forged.
The better answer is Django needs to get rid of a client referer check in its CSRF mechanism, it's pointless and makes no sense...
I want to redirect all http requests to https in my django app. The app has also an api through which I make request to database. Those requests are made through http protocol and I want to redirect them to https as well . Below configuration works well with requests made in web browser (http are correctly redirected to https and the website displays). However, the requests through api cause 301 error (Moved Permanently). Am I missing something here? This is my nginx configuration:
server {
listen 80;
server_name myurl.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name myurl.com;
ssl_certificate /path_to_cer;
ssl_certificate_key /path_to_key;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
#proxy_buffering off;
}
Django settings:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
To distribute load and implement security in our application we have taken elastic Load Balancer from amazon and SSL is configured on it.Now the redirection from http to https is not working in nginx configuration on server or instances which is attached on ELB.
Here is following nginx configuration:-
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name new.example.com;
access_log /var/log/nginx/domain-access.log;
location / {
proxy_read_timeout 90;
proxy_connect_timeout 90;
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;
proxy_pass http://127.0.0.1:8000;
}
}
Firstly the server is not supporting https URLs then I add some proxy settings in configuration but now issue is that redirection is not working i have used the following commands in ngnix configuration to redirect http to https :-
#version 1
server{
return 301 https://$server_name$request_uri;
}
#version 2
server {
rewrite ^(.*) https://$host$1 permanent;
}
Application deployed on server is build using django framework.
When I've done something similar, then I've set up the ELB HTTPS to redirect to HTTP port 80 on the node. I've then set up a second nginx vhost on the node, e.g. on port 81, which directs to return 301 https://$server_name$request_uri; and set up the ELB http listener to redirect to that port (where $server_name obviously points to the domain CNAME of the ELB)
I then make sure that the instances behind the ELB cannot be accessed from outside my VPC using security groups.
If you are using Django, you can use it to do the redirection, this give a lot of flexibilty like enabling HTTPS redirects only on production server or choose which urls to redirect from:
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
# Redirect to HTTPS in production
SECURE_SSL_REDIRECT = not DEBUG
# Disable redirection on this urls
SECURE_REDIRECT_EXEMPT = [
'^legacy/api/',
]
Goal: I want to serve django-rest-framework(drf) responses over https.
I'm trying to understand why my setup isn't working, whether it can be fixed by a simple settings change in one of the components, or if I should try a different approach.
I have a drf application served by gunicorn. Gunicorn is behind an NGINX proxy. I also have some static content served by NGINX. This setup has worked fine for plain old http.
Then I set NGINX to listen over ssl (,and installed certs, etc.). The static content works over https. I can still get to drf via http, but I get nothing / timed out over https. The gunicorn logs haven't been that helpful to me, but django dev server gives "dev server doesn't work over https" when sent a request.
Here is my first attempt at the nginx config (anonymized). This was mostly from reading the gunicorn and nginx manuals.
server {
server_name example.com;
listen 443 ssl;
ssl_certificate /path/to/cert;
ssl_certificate_key /path/to/key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ...
location /static/{
alias /path/to/static/content/;
}
location / {
return 301 $scheme://example.com/static;
}
location /drf/{
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Real_IP $remote_addr;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://127.0.0.1:6565; # bound to gunicorn, can be reached from http://example.com:6565 - ideally want to be available from https://example.com:6565
}
}
server {
listen 80;
server_name example.com;
return 301 https://example.com
}
I don't think there is an additional step for gunicorn. On the DRF side, I read the relevant Django security section and tried using the SECURE_SSL_REDIRECT = True (new in 1.8 - not addressed in a lot of existing questions) and SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https').
I also tried with a redirect, but this was sort of a shot in the dark:
...after `proxy_pass` above, and commenting out proxy_redirect off:
proxy_redirect http://127.0.0.1:6565 https://example.com/drf
Ubuntu 14, Gunicorn 19, Nginx 1.1,
Django 1.8 (DRF 3.2)
Update:
NGINX Error logging:
I get nothing if I go to https://example.com:6565. Here is an error from nginx's error log for a request to https://example.com/drf/endpoint.
2015/09/08 13:53:52 [error] 12564#0: *14 connect() failed (111: Connection refused while connecting to upstream, client: 155.xxx.xxx.xx, server:example.com, request:"GET /drf/endpoint", upstream: "http://127.0.0.1:6565/drf/endpoint", host: "example.com"
I'm receiving a 404 error from Nginx when attempting to return an HttpResponseRedirect from Django. This is all happening under HTTPs The flow goes something like this:
User goes to a page
Enters some information in a form
The view process the form after POST and then attempts to redirect the user to a different page.
Except, instead of redirecting to the page, Nginx just eventually servers its 404 page.
I can get this to work in development while not under Nginx and HTTPs, so I suspect this has something to do with my Nginx setup. I have this working successfully on other servers so I'm unsure why I cannot get it working here
Sample Django view:
#login_required()
def index(request):
if request.method == 'POST':
form = ShortenerForm(request.POST)
if form.is_valid():
# Do stuff
return HttpResponseRedirect(reverse('shortener_thankyou'))
else:
form = ShortenerForm()
return render(request, 'shortener/index.html', {'form': form})
Nginx
upstream apollo2_app_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server unix:/webapps/apollo2/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name apollo.mydomain.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443;
ssl on;
ssl_certificate /etc/nginx/ssl/bundle.crt;
ssl_certificate_key /etc/nginx/ssl/mydomain.com.key;
server_name apollo.mydomain.com;
client_max_body_size 4G;
keepalive_timeout 70;
access_log /webapps/apollo2/logs/nginx-access.log;
error_log /webapps/apollo2/logs/nginx-error.log;
location /static/ {
alias /webapps/apollo2/static/;
}
location /media/ {
alias /webapps/apollo2/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://apollo2_app_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /webapps/apollo2/static/;
}
}
Nginx error
2015/04/24 11:04:10 [error] 18139#0: *3395 upstream prematurely closed connection while reading response header from upstream, client: 192.168.0.119, server: apollo.mydomain.com, request: "POST /shortener/ HTTP/1.1", upstream: "http://unix:/webapps/apollo2/run/gunicorn.sock:/shortener/",
I've tried a number of different solutions involving proxy_set_header X-Forwarded-Protocol $scheme; in Nginx and Djangos SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') but without luck.
It turned out that this had nothing to do with Nginx, SSL or Django. IT changed one of our DNS servers without notifying me. The response was timing out because it could not resolve DNS. Updating to the new DNS server in /etc/resolv.conf solved the issue.