NGINX + ModSecurity v3 + OWASP CRS on Ubuntu 24.04 LTS – Step by Step – Part 1

Part 1 – Compiling and Installing the Modules and Enabling ModSecurity v3

This guide shows the complete installation of ModSecurity v3 with NGINX and the OWASP Core Rule Set (CRS) on an Ubuntu server – including correct module paths, symlink conventions, and example tests.

  • In Part 1 you install the necessary modules and enable ModSecurity v3.
  • In Part 2 we add the OWASP Core Rule Set (CRS).
  • In Part 3 we cover the required exceptions for the OWASP Core Rule Set to run a WordPress website.

1. Install Dependencies

Bash
sudo apt update
sudo apt install -y git g++ build-essential autoconf automake libtool \
  libpcre3 libpcre3-dev libpcre2-dev libxml2 libxml2-dev libyajl-dev \
  pkg-config zlib1g zlib1g-dev libcurl4-openssl-dev \
  liblua5.3-dev libgeoip-dev doxygen

2. Compile and Install ModSecurity v3

First you build ModSecurity. Then, in a separate step, you build the module for NGINX integration.

Bash
cd /usr/local/src
sudo git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity
cd ModSecurity
sudo git submodule init
sudo git submodule update
sudo ./build.sh
sudo ./configure
sudo make -j"$(nproc)"
sudo make install

After a successful installation, ModSecurity was set up and the directory /usr/local/modsecurity was created, among others.

3. Build the NGINX Module

You need to determine which version of NGINX is in use on your system:

Bash
nginx -v

In my case, output was:

Output
nginx version: nginx/1.24.0 (Ubuntu)

Depending on that, you’ll need the NGINX source to build the ModSecurity module. In the example code, we clone ModSecurity‑nginx.git and then download the NGINX 1.24.0 source.

Then you build only the NGINX modules with sudo make modules.

Bash
cd /usr/local/src
sudo git clone https://github.com/SpiderLabs/ModSecurity-nginx.git
sudo wget http://nginx.org/download/nginx-1.24.0.tar.gz
sudo tar -xzf nginx-1.24.0.tar.gz
cd nginx-1.24.0
sudo ./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
sudo make modules

4. Place and Enable the Module

You should now be in the directory /usr/local/src/nginx-1.24.0.

Copy the created NGINX module into the modules directory, then create the file mod-modsecurity.conf and the symlink in nginx/modules-available.

This configuration assumes:

  • existing modules are in /usr/share/nginx/modules-available
  • symlinks for enabled modules are in /etc/nginx/modules-enabled
Bash
sudo cp objs/ngx_http_modsecurity_module.so /usr/lib/nginx/modules/
sudo chmod 0644 /usr/lib/nginx/modules/ngx_http_modsecurity_module.so
echo "load_module modules/ngx_http_modsecurity_module.so;" | sudo tee /usr/share/nginx/modules-available/mod-modsecurity.conf
sudo ln -s /usr/share/nginx/modules-available/mod-modsecurity.conf /etc/nginx/modules-enabled/50-modsecurity.conf

5. Create ModSecurity Configuration

Next, create the base configuration for ModSecurity.

Bash
sudo mkdir -p /etc/nginx/modsec
cd /etc/nginx/modsec
sudo cp /usr/local/src/ModSecurity/modsecurity.conf-recommended ./modsecurity.conf
sudo cp /usr/local/src/ModSecurity/unicode.mapping .

If the unicode.mapping file is missing, you can download it via wget:

Bash
wget https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/unicode.mapping -O /etc/nginx/modsec/unicode.mapping

6. Enable Basic Rules

You have just copied modsecurity.conf into /etc/nginx/modsec.

Check that the following parameters are set correctly in the file:

modsecurity.conf excerpt
SecRuleEngine On
SecAuditEngine RelevantOnly
SecAuditLog /var/log/modsec_audit.log

7. Integrate the Module into Your Site and Test

Open your site’s NGINX config file.

In the server block, right after listen, insert the following:

example.com.conf excerpt
server {
  listen ...
  server_name ...
  
  	# activate ModSecurity
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;

Now create the file /etc/nginx/modsec/modsec_test.conf:

Bash
sudo nano /etc/nginx/modsec/modsec_test.conf

Add the following content:

modsec_test.conf
# For testing purpose
SecRule REQUEST_URI "@contains blockme" \
    "id:1001,phase:1,deny,status:403,msg:'Test rule triggered',chain"
    SecRule REQUEST_URI "@beginsWith /test/"

Then edit /etc/nginx/modsec/modsecurity.conf:

Bash
sudo nano /etc/nginx/modsec/modsecurity.conf

Add this Include line at the end:

modsecurity.conf excerpt
Include /etc/nginx/modsec/modsec_test.conf

You must now reload nginx:

Bash
sudo nginx -t && sudo systemctl reload nginx

From your local computer, send a test request using curl, or just enter the address in your web browser.

Bash
curl -i "https://softworx.at/test/?test=blockme"

If you use curl, the result should look similar to:

Output
HTTP/2 403 
server: nginx/1.24.0 (Ubuntu)
date: Wed, 11 Jun 2025 15:21:00 GMT
content-type: text/html
content-length: 162
strict-transport-security: max-age=63072000; includeSubDomains; preload

The important part is HTTP/2 403, the HTTP status code for Forbidden, meaning the request was blocked and ModSecurity is working.

Installation of the OWASP Core Rule Set

In Part 2, you’ll learn how to install and activate the OWASP Core Rule Set..

Comments

Leave a Reply