I want to block some user agents but NGinx seems not to see it.
I did use the map
calling the map from the http section and having the test in the server section (like show on many tutorials)
map $http_user_agent $badagent {
default 0;
~*archive.org_bot 1;
~*Anemone 1;
~*Ant.com 1;
~*Baidu 1;
~*Bot/1.0 1;
~*Companybook 1;
~*Go-http-client 1;
~*Pcore-HTTP 1;
}
then in the server section
if ($badagent) {
return 444;
}
i've tried that too
if ($badagent = 1) {
return 444;
}
to make it easier i even tried that :
if ($http_user_agent="Mozilla") {return 404;}
and
if ($http_user_agent = "Mozilla") {return 404;}
there is no error, but even after restart, my browser is not blocked. What did i did wrong ?
I found the issue.
I have a nginx.conf file AND a mydomain.conf file.
Whenever the instruction was in my main nginx.conf file (that is parsed and part of the config), the instruction/test was not taken into consideration.
But as soon as i moved the intruction in mydomain.conf file, then everything was working fine.
Related
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.
I want to set different URLs for desktop and mobile
I already tried this code in nginx.conf file
http {
server {
listen 80;
server_name 1.2.3.4;
set $mobile_request false;
if ($http_user_agent ~* '(Mobile|WebOS)') {
set $mobile_request true;
}
if ($mobile_request = true) {
rewrite ^ /high-mobile/html; #path of my mobile html files
break;
}
if ($mobile_request = false) {
rewrite ^ /high/html; #path of my desktop html files
break;
}
location / {
root /home/ubuntuvm/; #root url
index index.html index.htm; #default home page
}
This is my code when i hit the url in browser it gave error like
redirected you too many times
Failed to load resource: net::ERR_TOO_MANY_REDIRECTS
http://1.2.3.4/high-mobile/html/#/:1 GET http://1.2.3.4/high-mobile/html/ net::ERR_TOO_MANY_REDIRECTS
Thankyou in advance.....
I got the solution
location = /high/ {
if ($mobile_request = true) {
return 301 $scheme://ip_addr/high-mobile/html/index.html#/;
}
Here is my attempt at a solution.
http {
server {
listen 80;
server_name 1.2.3.4;
set $mobile_request false;
#If it's a mobile user-agent, set it to true.
if ($http_user_agent ~* '(Mobile|WebOS)') {
set $mobile_request true;
}
#If it's not a request to a mobile site, append "desktop" to the "mobile_request" variable.
if ($request_uri !~ "^.*/high-mobile/.*$"){
set $mobile_request "${mobile_request}+desktop";
}
#If it is a mobile user-agent AND it is a request to the desktop site, redirect to the mobile site.
if ($mobile_request = "true+mobile") {
#Clear the variable of any data, so that it doesn't induce a redirect loop with old data for new requests.
set $mobile_request "";
rewrite ^ /high-mobile/html; #path of my mobile html files
break;
}
location / {
root /home/ubuntuvm/; #root url
index index.html index.htm; #default home page
}
}
}
The assumption made in the solution:
All requests are by default to the desktop site and /high/ is in the URI, thus there is no need to check the negation of $mobile_request.
If this is not the case, you'll need to post your full NGINX configuration as well as the directory structure you're using. Any config more complicated than this is generally wrong unless you're trying to do something very specific or you're supporting a legacy infrastructure. I hope this helps.
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.
Directory Structure:
project
|__profile_pictures
|__user1.png
|__static
|__js
|__main.js
Requests:
1) /js/main.js
2) /profile_pictures/user1.png
Nginx configuration:
location ~/profile_picture(^.+\.(jpg|jpeg|gif|png)$) {
alias /home/chirag/Desktop/project/profile_pictures/$1;
expires -1;
}
location ~*(^.+\.(jpg|jpeg|gif|css|png|js|ico|eot|otf|svg|ttf|woff|hbs)$) {
alias /home/chirag/Desktop/project/static/$1;
expires -1;
}
First request should goto static folder.(Working)
Second request should goto profile_pictures folder.
Second request is failing. What am i missing here?
The problem is with the first profile picture location block. So the right way to handle this would be
location ~ ^/profile_picture/(.+\.(jpg|jpeg|gif|png)$) {
alias /home/chirag/Desktop/project/profile_pictures/$1;
expires -1;
}
location ~*(^.+\.(jpg|jpeg|gif|css|png|js|ico|eot|otf|svg|ttf|woff|hbs)$) {
alias /home/chirag/Desktop/project/static/$1;
expires -1;
}
Do not use the ^ in the middle of a regex. It is meant to suggest the beginning. Also you missed the following / after the profile picture. The new location block should work for you.
Good Luck Mate. Cheers
I'm trying to figure out how to do the following:
Request is coming in.
HttpLuaModule performs some action against the request. If request is valid than Lua will finish processing with ngx.exit(202). But there are some conditions that may (and will) occur during the processing and nginx might return 403 , 404, 503 Errors.
What I want to do is to write to access logs only requests that have 200 Status code.
Basically I would like to do something like this:
location /foo {
content_by_lua_file "/opt/nginx/lua/process.lua";
if (status == 200) {
access_log "/path/to/the/access_log"
}
I'm very new to both nginx and lua so for me it's a bit of a challenge to figure out where to place and if statement (ether after content_by_lua_file or in side lua file) and what this if statement should look like.
nginx 1.7.0+ allows using an if condition in access_log directive itself.
access_log path [format [buffer=size [flush=time]] [if=condition]];
The if parameter (1.7.0) enables conditional logging.
A request will not be logged if the condition evaluates to “0” or an empty string
Combined with map directive its possible to send log events to different logs based on various conditions.
http {
map $status $normal {
~^2 1;
default 0;
}
map $status $abnormal {
~^2 0;
default 1;
}
map $remote_addr $islocal {
~^127 1;
default 0;
}
server {
access_log logs/access.log combined if=$normal;
access_log logs/access_abnormal.log combined if=$abnormal;
access_log logs/access_local.log combined if=$islocal;
}
}
http://nginx.org/en/docs/http/ngx_http_log_module.html
http://nginx.org/en/docs/http/ngx_http_map_module.html
you can do it by using ngx.log and log_by_lua directives.
location /conditional_log{
log_by_lua 'if ngx.status == 200 then ngx.log(ngx.ERR, "It is 200") end';
content_by_lua 'ngx.say("I am ok") ngx.exit(200)';
}
In the above code, we use log_by_lua which is called while running in log phase. In that if ngx.status == 200, we use ngx.log to trigger the logging using ngx.log.
This will write to error_log. Not sure how to write it to access_log.
For reference
http://wiki.nginx.org/HttpLuaModule#ngx.log
http://wiki.nginx.org/HttpLuaModule#log_by_lua
In every question is a part of answer. You were very close:
if ($status != "200") {
access_log off;
}
Check info for version availability here.
http://nginx.org/en/docs/http/ngx_http_core_module.html#variables
Also, almost all access log format vars are available in "modern" versions:
http://nginx.org/en/docs/http/ngx_http_log_module.html
This is the solution I came up with:
auth.lua
-- Some logic goes here
-- ....
-- ....
ngx.var.return_status = 200
nginx.conf
http {
lua_package_path .....;
lua_package_cpath ....;
rewrite_by_lua_no_postpone on;
server {
set $return_status 1;
location /foo {
rewrite_by_lua_file "<apth_to_aut.lua";
if ($return_status = 200) {
access_log <path_to_access_log> format;
return 200;
}
}
}
}