NGINX - Reverse Proxy Web Server with ModSecurity

This article details how-to install and configure NGINX as a reverse proxy web server with ModSecurity 3 and the latest OWASP CRS coreruleset.

ModSecurity 3 and OWASP CRS will be installed to facilitate a WAF - web application firewall on NGINX to protect an upstream web server.

 

Install NGINX Server

We need to build www/nginx from ports to include the modsecurity3 dynamic module.

Begin by opening NGINX's port configuration options:
make -C /usr/ports/www/nginx config

In the Third-party modules section select [X] MODSECURITY3 and click OK to save the new configuration options. This configures NGINX to install the ModSecurity connector module, and makes the security/modsecurity3 port a dependency which will also be built and installed.

Build and install NGINX:
make -C /usr/ports/www/nginx make install clean

 

Configure NGINX as a Reverse Proxy Server

In the provided example below, NGINX is configured to redirect all unencrypted connection requests to https:// port 443.

All requests to https:// port 443 are proxied to the upstream web server which needs to be configured to listen on the specified proxy port for unencrypted proxied connections from NGINX.

NGINX will handle all encrypted sessions with the client, freeing up those resources on the upstream web server.

Create a new /usr/local/etc/nginx/nginx.conf file with the following configuration:

worker_processes auto;

events {
    worker_connections 768;
}

http {
	ssl_certificate 	/path/to/fullchain.pem;
	ssl_certificate_key	/path/to/privkey.pem;

	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto $scheme;

	server {
		listen 80;
		server_name example.org;

return 301 https://example.org$request_uri; } server { listen 443 ssl; server_name example.org;
location / { proxy_pass http://127.0.0.1:8080; } } }

Please note that the example above details only the most basic configuration to achieve the desired outcome. It is likely your nginx.conf will include additional configuration options to secure your web server such as additional security headers and SSL options.

Start the NGINX service and verify that it is operating correctly and that your web site is accessible.
service nginx start

 

Configure ModSecurity3

The security/modsecurity3 port installs both a default recommended modsecurity.conf file, and the required unicode.mapping file.
To enable ModSecurity active blocking, edit /usr/local/etc/modsecurity.conf changing SecRuleEngine from DetectionOnly to On.

SecRuleEngine On

 

Install the OWASP CRS Ruleset

Download the latest release of the OWASP CRS coreruleset at https://github.com/coreruleset/coreruleset

untar or unzip the downloaded package into the /usr/local/etc/modsecurity/ folder.
tar -xvf coreruleset-4.16.0-minimal.tar.gz -C /usr/local/etc/modsecurity/ or
unzip -d /usr/local/etc/modsecurity/ coreruleset-4.16.0-minimal.zip

Rename the directory to coreruleset
mv /usr/local/etc/modsecurity/coreruleset-4.16.0/ /usr/local/etc/modsecurity/coreruleset/

Create a new crs-setup.conf by copying the example file
cp /usr/local/etc/modsecurity/coreruleset/crs-setup.conf.example /usr/local/etc/modsecurity/coreruleset/crs-setup.conf

Create a new main.conf configuration file to include ModSecurity's base configuration followed by OWASP CRS configuration and rules files.
vi /usr/local/etc/modsecurity/main.conf

# Include the recommended configuration
Include /usr/local/etc/modsecurity/modsecurity.conf

# Include OWASP CRS rules
Include /usr/local/etc/modsecurity/coreruleset/crs-setup.conf
Include /usr/local/etc/modsecurity/coreruleset/plugins/*-config.conf
Include /usr/local/etc/modsecurity/coreruleset/plugins/*-before.conf
Include /usr/local/etc/modsecurity/coreruleset/rules/*.conf
Include /usr/local/etc/modsecurity/coreruleset/plugins/*-after.conf

 

Load and Enable ModSecurity in NGINX

Load and enable the ModSecurity module in NGINX by adding the following options to /usr/local/etc/nginx/nginx.conf

At the very top of nginx.conf add:

load_module /usr/local/libexec/nginx/ngx_http_modsecurity_module.so;

To enable ModSecurity globally in NGINX, add the following to the http { } block of nginx.conf:

modsecurity on;
modsecurity_rules_file /usr/local/etc/modsecurity/main.conf;


Restart NGINX to load ModSecurity and the OWASP CRS ruleset.

service nginx restart

 

Test ModSecurity Detection and Blocking

To test if ModSecurity is working, execute the following command, or copy/just paste the URL into a browser:
curl -I "https://example.org/?search=<script>alert('CRS+Sandbox+Release')</script>"

If ModSecurity is working, it will block the request and return an error 403 Forbidden response.

 

Logging

NGINX by default logs to /var/log/nginx/error.log and /var/log/nginx/access.log.
NGINX will also log ModSecurity's block actions with error 403 in these logs.

ModSecurity's audit log is /var/log/modsec_audit.log by default.
It provides all the specific details of the request being blocked i.e. the request_uri, the attack vector, anomaly scoring etc.

Note: If you intend to rotate and retain copies of modsec_audit.log using newsyslog for example, then the NGINX service must be fully restarted with service nginx restart after log rotation to continue audit logging normally.