Nginx set_real_ip_from AWS ELB load balancer address

Solution 1:

If you can guarantee that all requests will be coming from ELB (I'm not familiar with it), you could try:

real_ip_header X-Forwarded-For;
set_real_ip_from 0.0.0.0/0;

That should tell nginx to trust an X-Forwarded-For header from anyone. The downside is that if anyone directly accesses your server, they would be able to spoof an X-Forwarded-For header and nginx would use the wrong client ip address.

Solution 2:

Today's best practice is to use VPC, so, then, you will know the exact CIDR for your ELB. Then, you can add something like this to your Nginx configuration file:

real_ip_header X-Forwarded-For;
set_real_ip_from 10.0.0.0/8;

Solution 3:

Use the VPC CIDR for set_real_ip_from You can find it in Amazon console under VPC => Your VPC (replace <your VPC CIDR here> with it):

real_ip_header X-Forwarded-For;
set_real_ip_from <your VPC CIDR here>;

Solution 4:

Setting the trusted range to 0.0.0.0/0 on Amazon ELB is for sure going to get you into trouble. You can guarantee that the requests comes from the ELB if you can configure the security group for your nginx server, but the original request will originate from any possible source (Amazon ELBs are public interfaces).

A simple test will reveal this:

curl --header "X-Forwarded-For: 1.2.3.4" "http://your-elb-dns-address/"

The logs on your nginx server will then show 1.2.3.4 as the real IP, which is a spoofed one. See IP Range for internal private IP of Amazon ELB for better answers.


Solution 5:

The realip_module states that in case of X-Forwarded-For, this module uses the last ip address in the X-Forwarded-For header for replacement. This module will not work when only real_ip_header and set_real_ip_form are set. This is because this module will use a proxy IP address instead of a client IP. To solve this real_ip_recursive directive should be enabled.

Further, if you have SSL certificates that are deployed and renewed on the instance (like say letsencrypt or certbot certificates). These certificate authorities might try to validate those certificates via IPV6.

So it is important to also have IPV6. So the Nginx config file should also contain set_real_ip_from IPV6 address.

real_ip_header X-Forwarded-For;
real_ip_recursive on;
set_real_ip_from <your VPC IPV4 CIDR here>;
set_real_ip_from <your VPC IPV6 CIDR here>;

if additional security resitrictions apply, we may also need to include set_real_ip_from VPC CIDR (both IPV4 and IPV6) for cloudfront/elb/ec2 subnets.