nginx url redirect to custom url - django

I have a domain binging a IP:
a.a.com -> 1.1.1.1
In 1.1.1.1 has a nginx , for access a.a.com/bbb/ to 2.2.2.2's django service.
`
#1.1.1.1
server {
listen 8090;
server_name localhost;
location /bbb/ {
proxy_pass 2.2.2.2:8000;
}
}
`
when I input a.a.com/bbb/, I can access, it's ok.
But when Django login's session timeout , It automatic redirect a.a.com:8090/bbb/.
I want to ask how to automatic redirect a.a.com/bbb/.
ps. the 8090 port cant access
Sorry my poor English , Thanks.

Use proxy_redirect off:
location /bbb/ {
proxy_pass 2.2.2.2:8000;
proxy_redirect off;
}
proxy_redirect off tells nginx that, if the backend returns an HTTP redirect, it should leave it as is. (By default, nginx assumes the backend is stupid and tries to be smart; if the backend returns an HTTP redirect that says "redirect to http://localhost:8000/somewhere", nginx replaces it with something similar to "http://yourowndomain.com/somewhere", or, in your case, "http://yourowndomain.com:8090/somewhere". Django is smart enough so there is no need for nginx to do such things.)

Related

Django CSRF verification failed with nginx reverse proxy

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

Django CSRF "Referer Malformed"... but it isn't

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...

How to deploy django on VPS with external subdomain.?

Good day.
I have a web app that I have developed using django. I tested fine on my local, and I'm happy with how it works.
However I'm facing an issue bringing it online I used those two guides to reach my deployment:
https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04
and
http://michal.karzynski.pl/blog/2013/06/09/django-nginx-gunicorn-virtualenv-supervisor/
However my page is giving me a forbidden page.
I suspect my issue is with the way I'm handling the subdomain. So the site . has been developed using php, and I have worked on my part with django and been provided with a subdomain which is member.domain.com, So I'm deploying it on the VPS and have to make it use the subdomain.
This is how my allowed hosts looks in the settings.py
ALLOWED_HOSTS = ['member.domain.com']
and
in my nginx:
upstream 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:/home/path/project/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name member.domain.com;
client_max_body_size 4G;
access_log /home/path/project/logs/nginx-access.log;
error_log /home/path/project/logs/nginx-error.log;
location /static/ {
alias /home/path/project/src/static/;
}
location /media/ {
alias /home/path/project/src/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://app_server;
break;
}
}
# Error pages
error_page 502 503 504 /500.html;
location = /500.html {
root /home/path/project/src/static/;
}
}
I'm not sure what I am doing wrong.
I will appreciate any help
To respond to 'example.com' and any subdomains, start the domain with a dot
ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
I didn't even try how to run django on subdomains, but from article link you shared, you missed some configuration in your settings.py
ALLOWED_HOSTS = ['member.domain.com']
Changed
ALLOWED_HOSTS = ['.domain.com']
Hope this will solve your problem

Elastic Beanstalk Http Redirect to Https

I know this question has been asked before, but nothing seems to be working for me. I've tried multiple different things, such as the answers described in these questions:
How to get Elastic Beanstalk nginx-backed proxy server to auto-redirect from HTTP to HTTPS?
Redirecting EC2 elb from http to https
None of them seem to work. I'm an aws noob, so I'm not entirely sure how editing config files works - or if I've done something wrong.
My setup is the following:
Route 53 points to Elastic Beanstalk (nginx)
ELB port configuration with ACM certificate (using tcp/ssl as it makes my websockets work)
nodejs app on port 8080
My current nginx.config file in my .ebextensions folder (got this from this article):
files:
"/tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf" :
mode: "000755"
owner: root
group: root
content: |
upstream nodejs {
server 127.0.0.1:8081;
keepalive 256;
}
server {
listen 8080;
set $fixedWWW '';
set $needRedir 0;
# nginx does not allow nested if statements
# check and decide on adding www prefix
if ($host !~* ^www(.*)) {
set $fixedWWW 'www.';
set $needRedir 1;
}
# what about that https? the traffic is all http right now
# but elastic load balancer tells us about the original scheme
# using $http_x_forwarded_proto variable
if ($http_x_forwarded_proto != 'https') {
set $needRedir 1;
}
# ok, so whats the verdict, do we need to redirect?
if ($needRedir = 1) {
rewrite ^(.*) https://$fixedWWW$host$1 redirect;
}
location / {
proxy_pass http://nodejs;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
gzip on;
}
But this doesn't seem to do anything. I've run out of ideas. I'm not sure whether I'm missing a step or something but I don't know what to do. As a workaround I've got my angularjs front end redirecting non-https requests, but this is too hacky and some of the DOM renders before the redirect, I'd like to redirect at the load balancer - where it should redirect.
It looks like you're trying to do both a redirect for non-WWW and for non-HTTPS connections. Have you tried the simpler case of just http:// -> https:// ?
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}
Sometimes it's easier to handle it via two redirects, one from HTTP to HTTPS and one from non-WWW to WWW. In fact, if you're going to register your site via HSTS (https-everywhere), they require this sort of approach.
Edit: Also, just noticed the first line of your config, you might want to try injecting the nginx file directly:
files:
"/etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf" :
It's pretty hard to update /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf" directly. I found this: https://github.com/awsdocs/elastic-beanstalk-samples/blob/master/configuration-files/aws-provided/security-configuration/https-redirect/nodejs/https-redirect-nodejs.config, which let's you set up the redirect, but that would have changed my other config files too much. The best way to go about it is create a redirect.config file in your .ebextensions folder:
container_commands:
https_redirect:
command: |
sed -i '/location \/ {/i \
set $redirect 0;\
if ($http_x_forwarded_proto != "https") {\
set $redirect 1;\
}\
if ($http_user_agent ~* "ELB-HealthChecker") {\
set $redirect 0;\
}\
if ($redirect = 1) {\
return 301 https://$host$request_uri;\
}\
' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf```

Using Django, switched from heroku + gunicorn to digitalocean + nginx + gunicorn, site now broken

I had my django app on heroku for a while with no problems. I now want to move it to a digital ocean droplet, partly as a learning exercise, partly for scalability (and cost) reasons.
After following this excellent tutorial almost to the letter, the app is working but with a huge gotcha: I now get an infinite redirect loop when I try to log in to the admin site. The first request is a POST ?next=/admin/ with the username and password, this gets a 302 response to redirect to GET /admin/, which gets a 302 response redirect to ?next=/admin/, and so on.
I have spent 2 or 3 hours with google and various nginx tutorials and this is the first time my "google the error message, copy and paste random code snippets, repeat" algorithm has ever failed me, I'm hoping the reason is that the error is trivial to solve and I just can't see it?
If it's not trivial to solve, let me know and I'll post more info.
Thanks in advance
edit 1: my nginx config file for the app is basically a verbatim copy of the tutorial. It looks like this:
upstream hello_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/hello_django/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name example.com;
client_max_body_size 4G;
access_log /webapps/hello_django/logs/nginx-access.log;
error_log /webapps/hello_django/logs/nginx-error.log;
location /static/ {
alias /webapps/hello_django/static/;
}
location /media/ {
alias /webapps/hello_django/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://hello_app_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /webapps/hello_django/static/;
}
}