Nginx conditionally allow all to react sub-route based on IP - nginx

I'm setting up an NGINX server and need to configure it to allow only certain IPs access to the root of a react application, but allow all to a certain subfolder (react route). Basically I need to allow all traffic to /sub/ but only a handful of IPs to the home directory /.
I tried
location /sub/* { allow all;}
location / {
allow x.x.x.x;
deny all;}
but was getting a 403 error when using any other IP address except the 'x.x.x.x'.
What's the correct way to achieve this?
Thanks.

Here is what you can try to do:
map $uri $disallow_by_route {
~^/subroute/ ""; # allow /subroute/... for all
default 1;
}
map $remote_addr $disallow {
x.x.x.x ""; # some allowed IP
y.y.y.y ""; # another allowed IP
default $disallow_by_route;
}
server {
...
location / {
if ($disallow) { return 403; }
...
}
}
However if your allowed pages used some assets (js, css, images etc.) from some other path than /subroute/... this config won't let them to load on restricted IPs. You can try to allow them checking the value of HTTP Referer header with a more complex map blocks chain:
map $http_referer $disallow_by_referer {
# use a regex for your actual domain here
~^https?://example\.com/subroute/ "";
default 1;
}
map $uri $disallow_by_route {
~^/subroute/ "";
# list all the other possible assets extensions (png, gif, svg, webp etc.) here
~\.(?:js|css)$ $disallow_by_referer;
default 1;
}
map $remote_addr $disallow {
x.x.x.x ""; # some allowed IP
y.y.y.y ""; # another allowed IP
default $disallow_by_route;
}
server {
...
location / {
if ($disallow) { return 403; }
...
}
}
Please note that this solution won't work if your server configuration (or react app itself) sets the referer policy to no-referer.

Related

How to bypass nginx proxy a list of IPS

I have an Nginx config with the redirect to holding pages:
location / {
...
if ($setholdingpage = 'True') {
rewrite (^.*$) /holding-page last;
}
proxy_pass $backend;
}
Also, I have a list of IPs that should be whitelisted and not redirected to holding pages. How it's possible to do?
You can use the Nginx geo module to create a variable based upon client IP address, you can specify individual IP addresses or CIDR ranges:
geo $bypassip {
default 0;
64.233.160.0/19 1;
66.102.0.0/20 1;
}
Then override your variable if the IP matches one in your list:
if ($bypassip = 1){
set $setholdingpage False;
}
I use a similar setup to block certain geographic regions but still allow Google crawlers to access my site.
You can make use of the allow deny directives.
If I get you correct the whitelist will be your $setholdingpage variable in some sort?
try this
server {
error_page 403=#holding;
location / {
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
proxy_pass http://backend;
}
location /#holding {
root /path/to/your/holding/html;
index holdingv1.html;
}
}
This will send the non-whitelisted IPs to the error-page you specified. The error_page can be in the location as well.
Not tested but this should do the trick.
References:
http://nginx.org/en/docs/http/ngx_http_access_module.html#allow

Whitelist allow for specific requests Nginx

I have a server and there is a Nginx in front. There are many requests which some of them contains special word example:
/posts/men/clouths
I have a whitelist ip file also. I want to write a rule in Nginx that if requests contains "men", only allow the request if requester's ip is in whitelist file.
If requests does not contains "men" allow the request anyway.
Done
http {
## load whitelist
map $remote_addr $deny {
default 0;
include /path/to/whitelist.txt;
}
server{
## check
set $is_white_list 0;
if ($request_uri ~ ".*men.*"){
set $is_white_list 1;
}
if ($deny) {
set $is_white_list 1$is_white_list;
}
if ($is_white_list = 1) {
return 403;
}
##// epg check
}

Different files by useragent in NGINX

How can I correctly write the configuration of the nginx server?
...
if the client has useragent (A) and it refers to http://somehost.domain/somefile.someextension
nginx responding a file from the root /file.zip
if the client has useragent (B) and it refers to http://somehost.domain/somefile.someextension
nginx responding a file from the root /file2.zip
if the client has useragent (C) and it refers to http://somehost.domain/somefile.someextension
nginx responding 403 error
...
I did this code:
map $http_user_agent $browser {
"~*Firefox" "/var/www/test1";
"~*Wget" "/var/www/test2";
"~*SomeUserAgent" "/var/www/test3";
}
server {
...
root $browser
But how do I get the condition to pass to any address http://somehost.domain/somefile.someextension?
You can use map, location and alias directives to map a specific URI to multiple files based on the value of a header.
For example (where all of the files are in the same directory):
map $http_user_agent $browser {
default "nonexistent";
"~*Firefox" "file.zip";
"~*Wget" "file1.zip";
}
server {
...
location = /somefile.someextension {
alias /path/to/directory/$browser;
if (!-f $request_filename) {
return 403;
}
}
}
The if block is only required to change the 404 response to a 403 response.
See this document for more.

Nginx Locations and Connection Permissions

I'm suffering a brute force attack, I need to look the access log and get the routes to block:
location /foo/{ deny all;}
location /foo2/{deny all;}
Since there are infinite routes I would need to spend a good time looking all the access log to block connections at those specific routes.
Instead of denying specific routes could I configure nginx to block connections on all other routes that don't exists in my application?
[]'s
Pedro
Make a list of first level folders and then you can block access to all not of them with a access required
events {
worker_connections 1024;
}
http {
map $request_uri $allowed_routes {
~^/(css|assets|js)/ "off";
/ "off";
default "Not allowed";
}
server {
auth_basic $allowed_routes;
auth_basic_user_file /var/www/html/.htpasswd;
location / {
echo "You can reach API $uri and $args, $arg_hash_folder";
}
}
}
You might consider other approaches also, but this one works well for me

alternative log file in nginx for local requests

How can I redirect access logs to alternative file if requests come from my local network (e.g. 192.168.x.x)?
I've found some hints how I can disable logs based on requester IP, but in my case I want to log these requests to another file so that for development purposes I'd see only my own logs only in that specific file.
The answer is in your referenced pages, you just need to reverse the 1s and the 0s.
This should work:
map $remote_addr $private_ip {
~^192\.168\. 1;
default 0;
}
map $remote_addr $public_local {
~^192\.168\. 0;
default 1;
}
server {
...
# access-private.log for requests from local network
access_log /path/to/access-private.log main if=$private_ip;
# access.log for all other requests
access_log /path/to/access.log main if=$public_ip;
...
}
See this and this for details.
EDIT: Actually the geo directive is more appropriate for mapping a $remote_addr:
geo $private_ip {
192.168.0.0/16 1;
default 0;
}
geo $public_local {
192.168.0.0/16 0;
default 1;
}
See this document for details.

Resources