Just don’t understand, in Django documents and other articles, allowed_hosts is not recommended to be [‘*’] for security reasons. But a website should be open to the whole internet, what value should it be?
But a website should be open to the whole internet
ALLOWED_HOSTS in Django settings does not mean who will be allowed to access your site. It simple means on which address your site will be accessible. for example www.google.com is the address of google site. That does not mean who will be allowed to access the site (Its already public).
To allow/disallow a particular user to access your site is usually done with firewall or with a proxy server like nginx.
what value should it be?
It simply mentions the list of address from where your site can be accessed. like ALLOWED_HOSTS = ['your_site.com', 'IP_ADDRESS_OF_YOUR_SITE'] for more information visit docs
And for why ['*'] being dangerous and why ALLOWED_HOST was added to django please refer to this post.
It should be set to your application domain. For example, if your domain is http://example.com then you need to set ALLOWED_HOSTS to:
ALLOWED_HOSTS = ['example.com']
Related
<ip> is showing an actual ip address, I just didn't include it in the title.
I believe this ip address is the internal ip of my EC2 instance. I'm using AWS Elastic beanstalk to host.
I see this question has been answered a lot on SO, and the answer is always to add the ip address to the ALLOWED_HOSTS, but in my case I've set ALLOWED_HOSTS=['*'] and I'm still getting the error.
The weird thing is, I'm only getting the error when I try to access the site from my phone. When I access from the desktop browser, it works fine...
Things I've tried:
I've double checked my elastic beanstalk deployment and the changes are definitely deployed.
Ok so this probably won't be the answer for other people but it was for me..
In my case, I was doing an http GET request from my frontend and forgot the extra "/" at the end of the url. My django urls.py defines the url with a slash at the end. My fix was to add the extra "/" when doing the http GET.
On my desktop, this was automatically handled because django would reply with an automatic redirect (302) and my desktop browser would go to the url with / at the end, but my phone was not doing the redirect!
This somehow was throwing the invalid HTTP_HOST header error.
For most people, the fix for an error message like this is to add all of your domains to the list of ALLOWED_HOSTS.
Oh and if you're using elasticbeanstalk like me, don't forget to add the AWS domain name. It should look something like this:
ALLOWED_HOSTS = ['<your-unique-id>.elasticbeanstalk.com',
'example.com', '<your-subdomain>.example.com']
DON'T do ALLOWED_HOSTS = ['*'] in prod!!
I always set my ALLOWED_HOSTS from an environment variable in Django. In my development .env I always set ALLOWED_HOSTS=.localhost,.127.0.0.1 and in production ALLOWED_HOSTS=mydomain.dom,my_ip_address
Now I am currently getting acquainted with Docker, and the question is what is the value of the ALLOWED_HOSTS in production. Should it remain as localhost, since I understand localhost will refer to the host container or should I set it as my domain. I am using Nginx for reverse proxy to forward requests.
You should set it to your domain. ALLOWED_HOSTS is used to determine whether the request originated from the correct domain name.
If you look at the docs for ALLOWED_HOSTS, you'll see that it is compared to the request's Host header, which is set by the User agent of the person visiting your site.
So although the Docker container is serving to it's own localhost, the request is originating from example.com
Check out this part of the docs to see exactly why host header validation is necessary, and you will probably better understand the purpose of ALLOWED_HOSTS
You can just use your regular domain/IP address. ALLOWED_HOSTS has to do with the headers of the user matching the IP of the server. The internal mechanics on the server are not the concern of it.
ALLOWED_HOSTS=mydomain.dom,my_ip_address
Is what you should go with.
Thanks for the answers and I did confirm its true. I would like to add that I also remembered that this can be confirmed by adding your domain to /etc/hosts pointing to 127.0.0.1. If the domain is not included in /etc/hosts, Django will throw a debug error telling you that the domain is not added to ALLOWED_HOSTS
Within my settings.py file, when I use ALLOWED_HOSTS of either my domain name or '*', I'm able to access my website. When I indicate only my server's static IP address, I get a 400 Bad Request error. Based on what I've read, this should work. Any thoughts as to why it might not be working?
I should mention that my site will be hosting a chaning list of domains, so it's important that I be able to use IP address in allowed hosts as opposed to a list of domain names.
Thanks
What is the difference between this two django settings :
ALLOWED_HOSTS
CORS_ORIGIN_REGEX_WHITELIST
ALLOWED_HOSTS
A list of strings representing the host/domain names that this Django site can serve. This is a security measure to prevent HTTP Host header attacks, which are possible even under many seemingly-safe web server configurations
CORS_ORIGIN_REGEX_WHITELIST
This is actually a variable expecting a third party package django-cors-headers.So the thing is when a browser starts a request through javascript to another domain (cross domain), browser will send a OPTIONS request first to get to know whether server is allowing the domain to accept request by checking Access-Control-Allow-Origin header.
Note
There are some other headers also using this like Access-Control-Allow-Headers , etc.
ALLOWED_HOSTS as the docs say is
A list of strings representing the host/domain names that this Django
site can serve.
So, if ALLOWED_HOSTS = ['www.mysite.com', 'mysite.com'] and you try to access from your browser blog.mysite.com then Django will be unable to serve this page. You should ALLOWED_HOSTS = ['www.mysite.com', 'mysite.com', 'blog.mysite.com'] Read the docs related to ALLOWED_HOSTS. They are pretty straightforward!
CORS_ORIGIN_REGEX_WHITELIST as the docs say (again):
A list of regexes that match origin regex list of origin hostnames
that are authorized to make cross-site HTTP requests.
This setting is most used when you have an API that exposes some endpoints for clients to consume. It allows browser's requests to these URLs patterns. So, if CORS_ORIGIN_REGEX_WHITELIST = [r'images.mysite.com', ] then the <img src="http://images.mysite.com/image.jpg />" will load successfully, but if <img src="http://big-images.mysite.com/image.jpg />" then it would fail.
More about CORS in Mozilla MDN.
I have hosted to django admin project on a local machine X.
http://10.4.x.y/myapp/admin works.
I have an external IP on another machine Y and i am doing a proxy pass
from the Y to X.
http://proxypassname.com/myapp/admin works.
But, When i click the link "Save" or "Save continue editing" button after editing in admin page, it redirects to local machine ip (i.e. http://10.4.x.y/myapp/blah_blah_blah).
How to make sure that the django project redirects to proxypass name instead of local IP?
This is happening because the admin redirects to IP it thinks it has. It gets in in the HTTP request's header.
However, the fix is very easy. Assuming you proxy server implements the X-Forwarded-For standard, it could be easily fixed.
in your settings.py, simply set:
USE_X_FORWARDED_HOST = True
and restart your Django.
If that doesn't work, you can try to see if your proxy sets a different kind of header, and write a middleware that does the same thing. It's the first example on Django's documentation chapter on middleware
I did these two things and it worked.
Whenever you add a ProxyPass, you should add ProxyPassReverse
SITE_ID should be set to the domain where you want to point this django project.