[HOWTO] Get real IP coming via AWS CloudFront and ELB to nginx

Background

pahud
2 min readJul 4, 2016

If you have EC2 instance running nginx behind ELB, it’s pretty easy to get real client IP from X-Forwarded-For header generated by ELB. But what if the ELB is still behind AWS CloudFront and you have multiple IP addresses in the X-Forwarded-For header, and you need to have correct remote_addr nginx variable so that other nginx modules can work properly, what can you do?

Solution

Yes, you need ngx_http_realip_module to help you and this blog(How to get the client IP when using CloudFront and nginx) by Johan Lundahl is helpful. However, the configuration could be very tricky and that’s why I wrote this article.

Generate the IP/CIDR list of AWS CloudFront

A little python like this can generate the IP/CIDR of CloudFront for you

nginx.conf

Then you have the configuration like this. Please note real_ip_header and real_ip_recursive have to be placed in the bottom of the IP list otherwise the module will not work properly(I’ve spent so much time on this).

        # your vpc subnet where ELB resides in
set_real_ip_from 10.0.0.0/8;
# AWS CloudFront IP/CIDR range
set_real_ip_from 52.84.0.0/15;
set_real_ip_from 54.182.0.0/16;
set_real_ip_from 54.192.0.0/16;
set_real_ip_from 54.230.0.0/16;
set_real_ip_from 54.239.128.0/18;
set_real_ip_from 54.239.192.0/19;
set_real_ip_from 54.240.128.0/18;
set_real_ip_from 204.246.164.0/22;
set_real_ip_from 204.246.168.0/22;
set_real_ip_from 204.246.174.0/23;
set_real_ip_from 204.246.176.0/20;
set_real_ip_from 205.251.192.0/19;
set_real_ip_from 205.251.249.0/24;
set_real_ip_from 205.251.250.0/23;
set_real_ip_from 205.251.252.0/23;
set_real_ip_from 205.251.254.0/24;
set_real_ip_from 216.137.32.0/19;
# always put the following 2 lines in the bottom of ip list
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Feature Request

Though it’s possible to retrieve the real client IP like this but it’s way too complicated and maintaining the IP/CIDR range in nginx.conf doesn’t make any sense as it may change over time. So I just created a feature request to AWS asking them to have a special header like CloudFront-Client-Real-Ip which contains just the real client IP from the view of CloudFront and pass it to the backend just like other CloudFront-* headers. Please note this is a built-in feature of Akamai as they have true-client-ip header for the backend. CloudFlare also ships with an out-of-the-box CF-Connecting-IP header as well. I didn’t see any reason why AWS CloudFront should not have this feature.

Hope this article helps.

Have fun!

--

--