Nginx supports allow
and deny
syntax to restrict IPs, e.g. allow 192.168.1.1;
. But if traffic goes through a reverse proxy, the IP will refer to the proxy's IP. So how can it be configured to whitelist a specific origin IP and deny all other incoming requests?
The PROXY protocol enables NGINX and NGINX Plus to receive client connection information passed through proxy servers and load balancers such as HAproxy and Amazon Elastic Load Balancer (ELB). With the PROXY protocol, NGINX can learn the originating IP address from HTTP, SSL, HTTP/2, SPDY, WebSocket, and TCP.
NGINX was initially designed as a reverse proxy server. However, with continuous development, NGINX also serves as one of the options to implement the forward proxy. The forward proxy itself is not complex, the key issue it addresses is how to encrypt HTTPS traffic.
The proxy_pass setting makes the Nginx reverse proxy setup work. The proxy_pass is configured in the location section of any virtual host configuration file. To set up an Nginx proxy_pass globally, edit the default file in Nginx's sites-available folder.
remote_addr will refer to the proxy, but you can configure the proxy to send the client address with header fields X-Real-IP/X-Forwarded-For.
Combined with the ngx_http_realip module, you can modify the incoming header to use the real client address for remote_addr. I believe this will work as expected with allow/deny syntax.
Just to clarify -- allow/deny syntax should be identical after enabling and configuring the module. Substitute your IP and your proxy addresses below.
Back-end nginx allow/deny:
location / {
allow <your ip>;
allow 127.0.0.1;
deny all;
}
Back-end nginx realip configuration:
set_real_ip_from <your proxy>;
real_ip_header X-Forwarded-For;
On your nginx proxy configuration:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
If you have multiple intermediate proxies involved, you'll need to enable real_ip_recursive and whitelist additional addresses with the set_real_ip_from directive.
I got it working with the following configuration, using the http_geo
module:
geo $remote_addr $give_access {
proxy 172.0.0.0/8; # <-- Private IP range here
default 0;
11.22.33.44 1; # <-- Allowed IP here
}
server {
# more config ...
location ^~ /secure_url_here {
if ($give_access = 0) {
return 403;
}
try_files $uri $uri/ /index.php?$args; # <-- Your directive here
}
}
Ref: http://nginx.org/en/docs/http/ngx_http_geo_module.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With