9

How do I set Django ALLOW_HOSTS on Elastic Beanstalk instance to allow Elastic Load Balancer IP?

Background

I deployed a Django website on Elastic Beanstalk. The website domain is added to ALLOW_HOSTS so normal requests are accepted by Django correctly.

ALLOWED_HOSTS = ['.mydomain.com']

Elastic Load balancer visit Elastic beanstalk instances directly with IP address for health check, so next line allow the health check:

# add Elastic Beanstalk instance local IP
aws_ip = requests.get('http://169.254.169.254/latest/meta-data/local-ipv4', timeout=0.1).text
ALLOWED_HOSTS.append(aws_ip)

But I still got invalid HOST IP errors that seems Elastic Beanstalk instances are visited with Elastic load balancer public IP. There are solutions online for EC2 deployments as you can set HTTPD softwares to set http HOST header when it's visited by IP directly. But we cannot config Apache on Elastic Beanstalk.

How do I add the Elastic load balancer IP to the ALLOW_HOSTS?

greybeard
  • 2,249
  • 8
  • 30
  • 66
Cloudream
  • 631
  • 6
  • 14

5 Answers5

21

There is no good reason to accept traffic that is directed to your ELB's IP. For the health check, my preferred method:

import requests
try:
    internal_ip = requests.get('http://instance-data/latest/meta-data/local-ipv4').text
except requests.exceptions.ConnectionError:
    pass
else:
    ALLOWED_HOSTS.append(internal_ip)
del requests
  • No complicated apache configuration, which depend on your domain
  • Fails quickly on dns, no need to rely on timeout
noamk
  • 1,179
  • 13
  • 15
  • To me this should be the accepted answer. solved the problem in a simple way, especially for software developers. PLUS, we can be assured the ELB health checks will catch when django raises an exception. – SamuelN Aug 30 '19 at 06:55
  • sorry, I down voted but Im wrong, please edit the answer to change my vote – Karl Zillner Oct 18 '19 at 00:04
  • Do you still see Invalid HTTP_HOST header errors even after adding this? I get hundreds of HOST HEADERs an hour even after I've added this. – James Parker Jan 17 '20 at 21:06
  • @JamesParker Yeah, I still get a lot of these host header errors even while using this fix. The host IP address in these errors IS to...something...in my AWS infrastructure as if I browse to one of these "bad" IP addresses I get my django site (well with a 400 error since it's not in ALLOWED_HOSTS) and the 400 error page is served with the cert for my domain. – Dustin Wyatt Dec 01 '22 at 22:01
4

I believe the best approach would be to configure Apache to handle request host validation. Even with beanstalk you should be able to configure Apache using .ebextensions.

The general idea is to check incoming requests for the 'ELB-HealthChecker/1.0' User-Agent and the health check URL you set as the request's REQUEST_URI. Those requests can have their host header changed to an allowed host with the RequestHeader set Host command.

If really don't want to configure Apache, you could implement a custom middleware to override Django's CommonMiddleware to allow the health checker requests to bypass Django's ALLOWED_HOST validation.

I went into greater detail in this answer if you need more on implementing one of these solutions.

Community
  • 1
  • 1
yummies
  • 686
  • 6
  • 14
1

Adding the local IP of the EC2 instance to the allowed hosts worked for me.

settings.py:

import socket

hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)

ALLOWED_HOSTS = ['...', local_ip]
tommypre
  • 23
  • 4
-1

You add list of IPs assigned to that host. Only the IP address no http:// or /latest/media...

Ramast
  • 7,157
  • 3
  • 32
  • 32
  • I replace the pseudo codes with actual codes... but those lines add elastic beanstalk instance IP only, I need to add elastic load balancer's IP – Cloudream Dec 23 '15 at 17:47
  • Aren't django app installed on __beanstalk instances__ ? If this is right then its beanstalk instances IPs that you should add not load balancers. `ALLOWD_HOSTS` doesn't specify which hosts can connect to your Django app, it specific what HOST http header is accepted. When you access django by domain then HOST header will have value like this `mydomain.com` when accessing by IP then HOST header will have that IP you are accessing as its value – Ramast Dec 23 '15 at 18:07
-2

In settings.py this is the configuration I use and it works well for me (for DEV at least) :

# AWS config for ElasticBeanstalk
ALLOWED_HOSTS = [
    '127.0.0.1',
    'localhost',
    '.compute-1.amazonaws.com', # allows viewing of instances directly
    '.elasticbeanstalk.com' 
]

I hope it helps.

vincedgy
  • 395
  • 4
  • 6
  • after doing `eb deploy` , the settings.py changes to `ALLOWED_HOSTS = ['.elasticbeanstalk.com' ]` . This sometimes gives me ALLOWED HOSTS error. I mean the error is not consistent. Any ideas? – utkarsh2k2 Apr 09 '19 at 07:03
  • 3
    this is totally unsafe......if I try to hack you using amazon domains in a single EC2 I will get success – Karl Zillner Oct 17 '19 at 23:56