Nginx — is it possible to allow access from certain subnets only combining with set_real_ip_from? - nginx

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?

The realip module is convenient when working with Nginx behind a reverse proxy or load balancer. But it does redefine $remote_addr which affects logging and the allow directive amongst others.
You can use $realip_remote_addr to get the address of your reverse proxy or load balancer.
You can test it using the geo block in your question, just include that variable as the address parameter.
For example:
geo $realip_remote_addr $someserver_allow {
default 0;
1.2.3.0/24 1;
4.5.6.0/24 1;
7.8.9.0/24 1;
}

Related

Assigning a custom variable to real_ip_header

I am trying to get the client IP when the requests are either coming through an application load balancer, or through AWS Cloudfront.
When its just coming through load balancer, I use X-Forwarded-For header (set by load balancer) and if its coming through the CloudFront, I use the custom header CloudFront-Viewer-Address set by Cloudfront.
Since the application is not aware if its coming through Cloudfront or ALB, I need to make the distinction, which I do it with a map:
map $http_CloudFront_Viewer_Address $remote_addr_header {
"~*" $http_CloudFront_Viewer_Address;
default $http_x_forwarded_for;
}
This map is working. I can log $remote_addr_header and it is getting the correct value.
However, this is not working:
real_ip_header $remote_addr_header;
Although the following are working:
real_ip_header X-Forwarded-For;
real_ip_header CloudFront-Viewer-Address;
So I am wondering if I am not able to directly assign a variable to real_ip_header, as the documentation says
Syntax: real_ip_header field | X-Real-IP | X-Forwarded-For | proxy_protocol;
Default:
real_ip_header X-Real-IP;
Context: http, server, location
Is there a way I can use the custom variable $remote_addr_header in real_ip_header?
As the name implies and documentation explicitly states (emphasis is mine):
The ngx_http_realip_module module is used to change the client address and optional port to those sent in the specified header field.
The directive interprets its argument as the name of a HTTP header where the IP address should be taken from - it is not being interpreted as an immediate constant as you may hope.

How to use Kubernetes DNS lookup for NGINX set_real_ip_from

I've written a NGINX whitelister service inside my K8 cluster. Because everything entering the cluster goes through the load balancer, I had to whitelist the forwarded IP address instead of the source IP directly.
In testing, I hardcoded it like this in the NGINX config:
set_real_ip_from x.x.x.x;
real_ip_header X-Forwarded-For;
Where x.x.x.x was the IP of the load balancer.
This worked.
I can't hardcode the IP in the actual deployment, so I was hoping to use the kube-dns service, like I used for the proxy_pass:
resolver kube-dns.kube-system.svc.cluster.local;
proxy_pass http://{service}.{namespace}.svc.cluster.local:$server_port;
Which also works.
However, this DNS lookup doesn't seem to work for set_real_ip_from:
resolver kube-dns.kube-system.svc.cluster.local;
set_real_ip_from {load balancer service}.kube-system.svc.cluster.local;
real_ip_header X-Forwarded-For;
When I run this, I just get access forbidden by rule, client: x.x.x.x(it's not in the whitelist), where x.x.x.x is the load balancer's IP. That kinda makes sense, since set_real_ip_from probably doesn't know to lookup the IP.
Is it possible to have NGINX do a DNS lookup for the forwarder address?
If not, maybe someone has a better way to do this.
Thanks!
I guess I just needed to sleep on this. Much simpler than I was making it.
I know the range that the load balancer should fall into, so I can just do a CIDR block for set_real_ip_from.
For example:
set_real_ip_from 10.60.0.0/16;
real_ip_header X-Forwarded-For;
And there is no need for a DNS lookup.

Nginx - Redirect many subdomains to a static Local IP

I have a VM with a set a servicies, all configurated in the same domain (Ej: *.local-mml.cloud), and I want to acces from my own PC, so I tried to use Nginx to redirect all to the local ip, but didn't work.
I dont realy know all the domains that I have to redirect, so becouse of that I want to use something that say 'All with .local-mml.cloud go to 192.168.x.x'
I tried this (but didn't work):
server {
server_name *.local-mml.cloud;
location / {
proxy_pass https://192.168.217.128;
}
}
I also tried setting each one in the /host file (in Windows), that's work but are to many and always find one more.
Aside notes: The VM have NAT network configuration, so is like a a
local network, because of that have an IP like 192.168.x.x.
try this
server {
listen 80 default_server;
server_name *.local-mml.cloud;
client_body_timeout 5s;
client_header_timeout 5s;
location / {
proxy_set_header Host $host;
proxy_pass hhttps://192.168.217.128/;
}
}

nginx reverse proxy, single domain, multiple subdirectories

Having trouble figuring this out.
I have nginx running on home.domain.com.
Within my home network, I have multiple web services that I'd like to access externally through a reverse proxy. No SSL for now, but I'll add that later. I need to set up a reverse proxy on subdirectories of home.domain.com/app{1-3} as I only have a valid cert for home.domain.com.
My current configuration:
server {
listen 80 default;
keepalive_timeout 120;
server_name home.domain.com;
location /app1/ {
proxy_pass http://internalIP1:8081/;
}
location /app2/ {
proxy_pass http://internalIP2:5000/;
}
}
When I try to access home.domain.com/app1, it should redirect to home.domain.com/app1/login/?next=%2F, but instead goes to home.domain.com/login/?next=%2F. This obviously throws a 404, as it's not available on the nginx server.
Thoughts? Suggestions?

Trying to get nginx status from a remote machine

I am trying to get stats from nginx from a remote machine. I added the ip address of the remote machine in the nginx config but when I run curl on the remote machine I get forbidden. How to I resovle? I reloaded the config.
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
allow xxx.xxx.xxx.xxx;
deny all;
}
curl http://mysite/nginx_status
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.0.13</center>
</body>
</html>
I was also facing same issue, i could not able to get nginx server status in remote machine.
Instead i was getting 403 forbidden error in web browser.
I made some modification in "nginx.conf" file which was in this path "/usr/local/nginx_fstack/conf". so things worked well for me.
Previously nginx.conf file was like this
http {
...
server {
...
location / {
root html;
index index.html index.htm;
}
location /nginx_status {
stub_status on;
access_log off;
allow xx.xx.xx.xx/24;
deny all;
}
...
}
}
I edited like this
http {
...
server {
location /nginx_status {
stub_status on;
access_log off;
allow xx.xx.xx.xx/24;
deny all;
}
...
}
}
So later from the browser "xx.xx.xx.xx/nginx_status" i got proper status like this below:
Active connections: 54
server accepts handled requests
12594 12594 12543
Reading: 0 Writing: 1 Waiting: 53
Things worked well for me :-)
Are you sure that the remote machine really has the IP you wrote into the config? What IP address is it? You can be behind NAT or sthg...
Also check the error log of Nginx, you should have some useful info available there... (I hope I rememeber correctly that it's written there. Anyway, why is access log off? At least for debugging you could use it...)
Amazon resolves IP's different internally. You should use the internal IP rather than the public-ipv4 address.
Log in to your server and run this:
ec2metadata --local-ipv4
ubuntu#ip-10-244-231-180:~$ ec2metadata --local-ipv4
10.244.231.180
Providing that your instances are within the same region, you should use this IP address instead.
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
allow 10.244.231.180;
deny all;
}
You could also use
allow 10.0.0.0/8; (although it's untested)

Resources