Skip to content

Instantly share code, notes, and snippets.

@dryan
Last active September 7, 2023 11:04
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dryan/8271687 to your computer and use it in GitHub Desktop.
Save dryan/8271687 to your computer and use it in GitHub Desktop.
Handling EC2 ELB health checks and Django's ALLOWED_HOSTS setting.
# Hosts/domain names that are valid for this site; required if DEBUG is False
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
ALLOWED_HOSTS = [
'yourdomain.tld',
'.compute-1.amazonaws.com', # allows viewing of instances directly
]
import requests
EC2_PRIVATE_IP = None
try:
EC2_PRIVATE_IP = requests.get('http://169.254.169.254/latest/meta-data/local-ipv4', timeout = 0.01).text
except requests.exceptions.RequestException:
pass
if EC2_PRIVATE_IP:
ALLOWED_HOSTS.append(EC2_PRIVATE_IP)
@JoarLeth
Copy link

Doesn't adding '.compute-1.amazonaws.com' to ALLOWED_HOSTS make it just as vulnerable as long as the attacker uses an EC2 instance? Requesting the hostname the same way as the IP would solve this if I'm not misstaken;
requests.get('http://169.254.169.254/latest/meta-data/public-hostname', timeout = 0.01).text

@jayachandp
Copy link

I'm getting bad request(400) when I'm trying requests.get. What could be the possible issue?

@jameserrico
Copy link

Don't you need the IP of the ELB? This looks like it's going to get me the IP of my instance.

@kakulukia
Copy link

thanx for the meta-data hint! this just solved my issue :)

@iandees
Copy link

iandees commented Jan 7, 2016

To answer @jameserrico above:

The Elastic Load Balancer HTTP health check will use the instance's internal IP [for the host header].

(From https://forums.aws.amazon.com/thread.jspa?messageID=423533)

@manelclos
Copy link

Works great! thanks!

@okc0mputer
Copy link

Still works!

@vaibhavhrt
Copy link

put your ec2 instance's private ip in allowed hosts if using single instance

@ohlr
Copy link

ohlr commented Jan 7, 2019

you do not need line 5 '.compute-1.amazonaws.com'. Works fine also without it.
Also the public-hostheader (@JoarLeth) is not required.

@threewordphrase
Copy link

Right on, good looks bud 👍

@eercanayar
Copy link

This is a great solution, congrats

@satishv
Copy link

satishv commented May 10, 2020

how about v6 addresses?

@mgax
Copy link

mgax commented Dec 29, 2020

Another option is to implement a middleware that returns a health check before Django's SecurityMiddleware (that checks the request against ALLOWED_HOSTS): https://gist.github.com/mgax/cf771b1991e68ca454693d5f3597ff04

@souravjamwal77
Copy link

souravjamwal77 commented Jun 1, 2022

Hi, I am stuck with this we have an ELB which uses the Round-Robin technique and we have 3-10 servers, and I couldn't get any single of them working. Which IP shall I put into the below line 11
EC2_PRIVATE_IP = requests.get('http://169.254.169.254/latest/meta-data/local-ipv4', timeout = 0.01).text

Please someone help me here

@anish5256
Copy link

anish5256 commented Sep 7, 2023

This Works for me

import requests

ALLOWED_HOSTS = [
    'yourdomain.tld',
    '.compute-1.amazonaws.com', # allows viewing of instances directly
]

EC2_PRIVATE_IP = None

try:
    token = requests.put("http://169.254.169.254/latest/api/token",
                         headers={"X-aws-ec2-metadata-token-ttl-seconds": "21600"}).text
                         
    EC2_PRIVATE_IP = requests.get("http://169.254.169.254/latest/meta-data/local-ipv4",
                                  headers={"X-aws-ec2-metadata-token": token}, timeout=0.01).text
                                  
except requests.exceptions.RequestException:
    pass

if EC2_PRIVATE_IP:
    ALLOWED_HOSTS.append(EC2_PRIVATE_IP)

@souravjamwal77
Copy link

Great,
I also have somewhat similar try/except block.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment