I need to deny access to site for all, except number of subnets, where the frontend proxies are located. At the same time I need to set real IP for further processing. The diagram looks something like this:
Some infrastructure proxying traffic to nginx
________ ______________________________________________ _________________
| | | | | |
| Client |------>|public-allowed ingress IP egress IP's|<--------->| Nginx |
|________| |______________________________________________| |_________________|
Allowed access
for «egress IP's»
only.
First I tried next configuration (all IP's are for example only):
server {
server_name someserver.tld;
# Subnets where frontend proxies are located
allow 1.2.3.0/24;
allow 4.5.6.0/24;
allow 7.8.9.0/24;
# Deny access bypassing proxies
deny all;
set_real_ip_from 1.2.3.0/24;
set_real_ip_from 4.5.6.0/24;
set_real_ip_from 7.8.9.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
… skipped …
}
As expected that's wasn't working: nginx sets the client's real IP, then checks the conditions and denies access to site for everybody. So I tried next:
# This block is outside of «server» section, so I expect it will be processed first
geo $someserver_allow {
default 0;
1.2.3.0/24 1;
4.5.6.0/24 1;
7.8.9.0/24 1;
}
server {
server_name someserver.tld;
# Deny access bypassing proxies
if ($someserver_allow != 1) {
return 403 "Bypassing the frontend is not allowed.";
}
set_real_ip_from 1.2.3.0/24;
set_real_ip_from 4.5.6.0/24;
set_real_ip_from 7.8.9.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
… skipped …
}
I expected that nginx will process geo
instruction, setting the $someserverallow
ignoring real_ip_header
in server
section, but it seems that I was wrong. To be sure I commented out entire if
clause and added next lines right after the geo
section:
map $someserver_allow $downstream {
default $remote_addr;
}
And also added next in server section:
add_header X-Downstream-IP "$downstream"
Requesting the frontend server with my browser I got my own IP address in X-Downstream-IP
header, not the IP of proxy server.
So, what's wrong with my configuration or, maybe, with my understanding of that how nginx processes instructions?