8.2.9 Installing ModSecurity WAF for Nginx
WAF ModSecurity is an open-source Web Application Firewall that provides protection for websites and web applications against attacks and vulnerabilities. ModSecurity analyzes HTTP traffic, blocks malicious requests, prevents SQL injections, XSS, brute-force attacks, scanning, and other common threats. It works as a module for Apache, Nginx, and IIS, supports flexible rule configuration (including OWASP CRS policies), and maintains detailed security logs.
System Requirements
- Virtual Server or Dedicated Server
- Ubuntu 22.04 LTS or Ubuntu 24.04 LTS
- CPU: minimum 2 cores;
- RAM: minimum 1 GB;
- SSD: at least 5 GB of free space;
- root or sudo access.
Security
Before you start, make sure that UFW or iptables rules are enabled, SSH access is restricted to keys, and all security updates are installed.
Server Preparation
First, update the packages and install dependencies:
sudo apt update && sudo apt install -y \
git build-essential autoconf automake libtool pkg-config \
libpcre3 libpcre3-dev libpcre2-dev libxml2 libxml2-dev libyajl-dev \
zlib1g zlib1g-dev curl wget
- git – to clone ModSecurity and ModSecurity-nginx repositories;
- build-essential, autoconf, automake, libtool, pkg-config – tools for building from source;
- libpcre3, libpcre3-dev, libpcre2-dev – libraries for regular expression support (used by ModSecurity and Nginx);
- libxml2, libxml2-dev – XML parser (required for ModSecurity);
- libyajl-dev – JSON parser (ModSecurity);
- zlib1g, zlib1g-dev – compression (ModSecurity, Nginx);
- curl – tool for downloading files (needed in later steps).
Create a working directory:
sudo mkdir -p /usr/local/src && cd /usr/local/src
Clone the ModSecurity repository, initialize submodules, and build the library:
git clone --depth 1 -b v3/master https://github.com/SpiderLabs/ModSecurity
cd ModSecurity
git submodule update --init
./build.sh
./configure
make
sudo make install
Clone the connector for Nginx:
cd ..
git clone https://github.com/SpiderLabs/ModSecurity-nginx.git
Download Nginx source code and compile it with the connector:
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -xf nginx-1.24.0.tar.gz
cd nginx-1.24.0
./configure --add-module=../ModSecurity-nginx
make
sudo make install
<$>[note]
By default, Nginx files will be installed into /usr/local/nginx
. To use standard paths like /etc/nginx
, /var/log/nginx
, and /usr/sbin/nginx
, add the --prefix
option to the ./configure
command and specify the paths manually.
<$>
Configuration
Create the configuration directory:
sudo mkdir -p /etc/nginx/modsec
sudo cp /usr/local/src/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
sudo sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/nginx/modsec/modsecurity.conf
Add OWASP CRS:
OWASP Core Rule Set (CRS) is a set of standard rules for ModSecurity that protect web applications against the most common attacks such as SQL injection, XSS, CSRF, Local File Inclusion (LFI), Remote File Inclusion (RFI), etc. It is an open-source project maintained by the OWASP community and regularly updated.
Install CRS and copy the rules:
sudo apt install modsecurity-crs -y
cd /etc/nginx/modsec
sudo git clone https://github.com/coreruleset/coreruleset.git
sudo cp coreruleset/crs-setup.conf.example crs-setup.conf
sudo cp -r coreruleset/rules .
sudo cp -r /usr/share/modsecurity-crs/rules /etc/nginx/modsec/
Connect the rules in nginx.conf
In the http section of nginx.conf
, add the following directives, for example right after default_type application/octet-stream; or before the server { block:
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
Run the command to create the configuration file:
nano /etc/nginx/modsec/main.conf
And add the following content:
Include /etc/nginx/modsec/modsecurity.conf
Include /etc/nginx/modsec/crs-setup.conf
Include /etc/nginx/modsec/rules/*.conf
Attack Logging
Create a log directory and set permissions:
sudo mkdir /var/log/modsecurity
sudo chown www-data: /var/log/modsecurity
In modsecurity.conf, specify the audit log path:
SecAuditLog /var/log/modsecurity/audit.log
Check the configuration and reload:
/usr/local/nginx/sbin/nginx -t && sudo /usr/local/nginx/sbin/nginx -s reload
WAF Testing
To test WAF, simulate an attack. The simplest way is to execute a SQL injection via URL directly in a web browser or using curl. WAF should detect the threat and return a 403 Forbidden error. Try:
http://your-domain.com/?id=1' OR '1'='1
The browser should return 403 Forbidden. Check the log with:
tail -f /var/log/modsecurity/audit.log
Common Issues and Solutions
Problem | Solution |
---|---|
WAF does not block anything | Ensure SecRuleEngine On and CRS rules are enabled |
Logs are empty | Check log file permissions and disk space |
403 error on valid forms | Enable DetectionOnly, find RuleID and add an exception |
CRS 901001 error | “CRS is deployed without configuration” — crs-setup.conf missing. Copy the file and restart service. |
Nginx build error | If ./configure doesn’t detect PCRE or Zlib, install libpcre2-dev and zlib1g-dev , then rebuild. |
Official Documentation and Useful Links