Ban IP address using Modsecurity - rules

I need a help, My operating systems (Centos 7), I installed Modsecurity & CSF.
How can I block any IP outside my country automatically that alert critical severity in Modsecurity.
Thank You

This isn't so easy as it may looks. First of all, by default, CRS is blocking all requests with critical score.
You will need to create few new rules to do what you want. It should look something like this:
# Do GeoIP lookup
SecRule REMOTE_ADDR "#geoLookup" \
"phase:2,\
id:9990001,\
nolog,\
pass"
SecRule TX:ANOMALY_SCORE "#ge %{tx.critical_anomaly_score}" \
"id:9990002,\
phase:2,\
block,\
t:none,\
chain"
SecRule GEO:COUNTRY_CODE "!#streq <ISO_CODE>"
Few notes:
replace <ISO_CODE> with ISO code of your country
rules must be run after CRS, so put them into file RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
you need to set SecGeoLookupDb in ModSecurity for GeoIP to work

Related

How to do reverse DNS lookup in Nginx

I have Nginx configuration where I want to allow a DNS name as I cant be certain on IP address.
{
satisfy any;
allow www.domain.com; // want to achieve this
}
With Nginx we cant achieve this.
Looked at this https://github.com/flant/nginx-http-rdns as a solution.
This module says it does reverse lookup but it didnt work and repo is very old and well maintained.
Another alternative is to use a shell script and do a dig or host on IP address but we dont want to use shell script with Nginx.
Alternate solution is to use a side car to do the DNS resolution and to add allow/deny rules.
If this still works you'll need to compile it for the same version of nginx that is installed. If you're using nginx from a repo then dynamically compile it and see if the following helps:
Download nginx src matching installed version and extract it.
$ cd nginx-1.x.x
$ ./configure --with-compat --add-dynamic-module=/path/to/nginx_module
$ make modules
make modules should result in a nginx module that you need to copy to /usr/lib/nginx/modules/ and load it with load_module modules/modulename.so in your nginx.conf.

Wordpress Varnish vcl Configuration

When I user apache in Varnish vcl config set :
.expected_response = 200;
and everything works correctly but when to install Litespeed I should change this parameter to :
.expected_response = 301;
What's the reason for this issue? Is this configuration right, or causing the other problem?
Basically people using LiteSpeed Web Server may want to use LSCache instead of Varnish. There're many reasons but I am not going to explain here.
You said with Litespeed only expect 301 status. It's possible something in the rewrite rules causing it. Please share the status code with following command.
curl -s -o /dev/null -w "%{http_code}" https://example.com
If it shows 301, then you may want to check your rewrite rules what making it different between Apache and LiteSpeed.
Best

Ubuntu + nginx - trying to install GeoIP module

I'm using vagrant (VVV actually) to run local wordpress installs. I want to test different behaviors for different GEO's on my local machine instead of upload it every time to the server which is annoying.
So, I've tried to install the GeoIP nginx module to the local machine with the following guide https://piwik.org/faq/how-to/faq_166/ (and a bit more google but it doesn't matter at the moment).
When I'm using ./configure the following is exists:
checking for GeoIP library ... found
checking for GeoIP IPv6 support ... found
I've also set the .dat files in my conf file, and set the $_SERVER (fastcgi_param) parameters - so they displayed when I'm printing the $_SERVER var.
But those GeoIP vars are empty. I'm not sure about the reason, but 2 things is bothering me. First, when I'm write nginx -V in the terminal the argument --with-http_geoip_module is missing. Second, could it actually works if the REMOTE_ADDR (IP) is not my real IP? (192.168.1.50 for example).
nginx is a bit strange for me, so sorry if something isn't exact..
--
Operating system - macOS, nginx version - 1.3.15, running with VVV (vagrant box)
If there is a reverse proxy in front of your nginx, use geoip_proxy to set IPs whose X-Forwarded-For-Header can be trusted.
You can also use that without actually having a reverse proxy when you're developing. Add your local IP to the geoip_proxy-list and set the X-Forwarded-For-Header to your public IP in your browser (use a plugin like Modify Headers).

Nginx variable for physical server name

I'm trying to setup response headers on my separate webservers that outputs the physical name of the machine that nginx is running on, so that I can tell which servers are serving the responses to our web clients.
Is there a variable that exists to do this already? Or do I just have to hardcode it per-server :(
You're after the $hostname common variable. Common variables are listed in the variable index.
The nginx access log documentation only shows variables that are specific to the access log:
The log format can contain common variables, and variables that exist
only at the time of a log write.
I guess you're looking for $hostname variable.
At first I thought the answer was to use the ENV variable and pull out the hostname from there https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html. But I couldn't get it to work for some reason.
However, this works like a charm:
perl_set $server_int 'sub { use Sys::Hostname; return hostname; }';
And example usage:
add_header 'Server-Int' "$server_int";
Just have to make sure your nginx is compiled with --with-http_perl_module - just run nginx -V to make sure. And that you have Sys::Hostname installed.
Warning: I at first used hostname to return the hostname in the Perl script, but while that did return the name, it for some reason aborted the rest of the output. I don't know if it's a bug with perl_set but you've been warned - using backticks in perl_set may be deadly.

How do you change the server header returned by nginx?

There's an option to hide the version so it will display only nginx, but is there a way to hide that too so it will not show anything or change the header?
If you are using nginx to proxy a back-end application and want the back-end to advertise its own Server: header without nginx overwriting it, then you can go inside of your server {…} stanza and set:
proxy_pass_header Server;
That will convince nginx to leave that header alone and not rewrite the value set by the back-end.
The last update was a while ago, so here is what worked for me on Ubuntu:
sudo apt-get update
sudo apt-get install nginx-extras
Then add the following two lines to the http section of nginx.conf, which is usually located at /etc/nginx/nginx.conf:
sudo nano /etc/nginx/nginx.conf
server_tokens off; # removed pound sign
more_set_headers 'Server: Eff_You_Script_Kiddies!';
Also, don't forget to restart nginx with sudo service nginx restart.
Like Apache, this is a quick edit to the source and recompile. From Calomel.org:
The Server: string is the header which
is sent back to the client to tell
them what type of http server you are
running and possibly what version.
This string is used by places like
Alexia and Netcraft to collect
statistics about how many and of what
type of web server are live on the
Internet. To support the author and
statistics for Nginx we recommend
keeping this string as is. But, for
security you may not want people to
know what you are running and you can
change this in the source code. Edit
the source file
src/http/ngx_http_header_filter_module.c
at look at lines 48 and 49. You can
change the String to anything you
want.
## vi src/http/ngx_http_header_filter_module.c (lines 48 and 49)
static char ngx_http_server_string[] = "Server: MyDomain.com" CRLF;
static char ngx_http_server_full_string[] = "Server: MyDomain.com" CRLF;
March 2011 edit: Props to Flavius below for pointing out a new option, replacing Nginx's standard HttpHeadersModule with the forked HttpHeadersMoreModule. Recompiling the standard module is still the quick fix, and makes sense if you want to use the standard module and won't be changing the server string often. But if you want more than that, the HttpHeadersMoreModule is a strong project and lets you do all sorts of runtime black magic with your HTTP headers.
It’s very simple: Add these lines to server section:
server_tokens off;
more_set_headers 'Server: My Very Own Server';
Simple, edit /etc/nginx/nginx.conf and remove comment from
#server_tokens off;
Search for http section.
Install Nginx Extras
sudo apt-get update
sudo apt-get install nginx-extras
Server details can be removed from response by adding following two lines in the nginx.conf (under http section)
more_clear_headers Server;
server_tokens off;
There is a special module: http://wiki.nginx.org/NginxHttpHeadersMoreModule
This module allows you to add, set, or clear any output or input header that you specify.
This is an enhanced version of the standard headers module because it provides more utilities like resetting or clearing "builtin headers" like Content-Type, Content-Length, and Server.
It also allows you to specify an optional HTTP status code criteria using the -s option and an optional content type criteria using the -t option while modifying the output headers with the more_set_headers and more_clear_headers directives...
If you're okay with just changing the header to another string five letters or fewer, you can simply patch the binary.
sed -i 's/nginx\r/thing\r/' `which nginx`
Which, as a solution, has a few notable advantages. Namely, that you can allow your nginx versioning to be handled by the package manager (so, no compiling from source) even if nginx-extras isn't available for your distro, and you don't need to worry about any of the additional code of something like nginx-extras being vulnerable.
Of course, you'll also want to set the option server_tokens off, to hide the version number, or patch that format string as well.
I say "five letters or fewer" because of course you can always replace:
nginx\r\0
with
bob\r\0\r\0
leaving the last two bytes unchanged.
If you actually want more than five characters, you'll want to leave server_tokens on, and replace the (slightly longer) format string, although again there's an upper limit on that length imposed by the length of the format string - 1 (for the carriage return).
...If none of the above makes sense to you, or you've never patched a binary before, you may want to stay away from this approach, though.
According to nginx documentation it supports custom values or even the exclusion:
Syntax: server_tokens on | off | build | string;
but sadly only with a commercial subscription:
Additionally, as part of our commercial subscription, starting from
version 1.9.13 the signature on error pages and the “Server” response
header field value can be set explicitly using the string with
variables. An empty string disables the emission of the “Server”
field.
After I read Parthian Shot's answer, I dig into /usr/sbin/nginx binary file. Then I found out that the file contains these three lines.
Server: nginx/1.12.2
Server: nginx/1.12.2
Server: nginx
Basically first two of them are meant for server_tokens on; directive (Server version included).
Then I change the search criteria to match those lines within the binary file.
sed -i 's/Server: nginx/Server: thing/' `which nginx`
After I dig farther I found out that the error message produced by nginx is also included in this file.
<hr><center>nginx</center>
There are three of them, one without the version, two of them included the version. So I run the following command to replace nginx string within the error message.
sed -i 's/center>nginx/center>thing/' `which nginx`
The only way is to modify the file src/http/ngx_http_header_filter_module.c . I changed nginx on line 48 to a different string.
What you can do in the nginx config file is to set server_tokens to off. This will prevent nginx from printing the version number.
To check things out, try curl -I http://vurbu.com/ | grep Server
It should return
Server: Hai
I know the post is kinda old, but I have found a solution easy that works on Debian based distribution without compiling nginx from source.
First install nginx-extras package
sudo apt install nginx-extras
Then load the nginx http headers more module by editing nginx.conf and adding the following line inside the server block
load_module modules/ngx_http_headers_more_filter_module.so;
Once it's done you'll have access to both more_set_headers and more_clear_headers directives.
Expanding on Parthian Shot's answer, you can actually replace the whole header and not only the value as long as the total length is the same:
sed -i 's/Server: nginx/My-Header: hi/' `which nginx`
Nginx-extra package is deprecated now.
The following therefore did now work for me as i tried installing various packages
more_set_headers 'Server: My Very Own Server';
You can just do the following and no server or version information will be sent back
server_tokens '';
if you just want to remove the version number this works
server_tokens off;
Are you asking about the Server header value in the response? You can try changing that with an add_header directive, but I'm not sure if it'll work. http://wiki.codemongers.com/NginxHttpHeadersModule

Resources