How to Install libmodsecurity + nginx on Ubuntu 14.04

ModSecurity, originally written as a web application firewall (WAF) for Apache servers, is the de facto standard for open-source WAF solutions. Recent work on the project has shifted focus toward providing a generic shared library that any web server can use to protect HTTP(S) requests. For more information about ModSecurity, visit the site here:

These instructions touch on building and configuring libmodsecurity for a DreamCompute instance running Ubuntu 16.04.

Building libmodsecurity

First, install the necessary packages and libraries used to build source projects, as well as libraries used specifically by libmodsecurity:

[root@server]# apt-get update && apt-get install -y automake bison build-essential \
               g++ gcc libbison-dev libcurl4-openssl-dev libfl-dev libgeoip-dev \
               liblmdb-dev libpcre3-dev libtool libxml2-dev libyajl-dev make \
               pkg-config zlib1g-dev

Next, download and unpack the most recent source of libmodsecurity. This is available from the ModSecurity GitHub project, on the libmodsecurity branch:

[root@server]# git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity
Cloning into 'ModSecurity'...
remote: Counting objects: 750, done.
remote: Compressing objects: 100% (721/721), done.
remote: Total 750 (delta 441), reused 107 (delta 23), pack-reused 0
Receiving objects: 100% (750/750), 651.13 KiB | 0 bytes/s, done.
Resolving deltas: 100% (441/441), done.
Checking connectivity... done.

Initialize and update the git submodules that libmodsecurity requires:

[root@server]# cd ModSecurity/
[root@server]# git submodule init
[root@server]# git submodule update

Finally, configure, build, and install the libmodsecurity library:

[root@server]# ./build.sh && ./configure && make && make install

Building nginx with libmodsecurity

Now that libmodsecurity has been installed and is available to be used by third-party programs, nginx can be compiled with the ModSecurity-nginx connector to load libmodsecurity and process requests.

First, grab the source for the nginx module wraps around libmodsecurity:

[root@server]# cd /root && git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
Cloning into 'ModSecurity-nginx'...
remote: Counting objects: 30, done.
remote: Compressing objects: 100% (30/30), done.
remote: Total 30 (delta 6), reused 8 (delta 0), pack-reused 0
Unpacking objects: 100% (30/30), done.
Checking connectivity... done.

Next, grab the nginx source and verify it. Start by downloading the source and its signature from nginx.org:

[root@server]# wget -q https://nginx.org/download/nginx-1.12.2.tar.gz{.asc,}

To verify the contents of the download, grab the developer's signing key from nginx.org:

[root@server]# curl -sS https://nginx.org/keys/mdounin.key | gpg --import
gpg: directory `/home/ubuntu/.gnupg' created
gpg: new configuration file `/home/ubuntu/.gnupg/gpg.conf' created
gpg: WARNING: options in `/home/ubuntu/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/home/ubuntu/.gnupg/secring.gpg' created
gpg: keyring `/home/ubuntu/.gnupg/pubring.gpg' created
gpg: /home/ubuntu/.gnupg/trustdb.gpg: trustdb created
gpg: key A1C052F8: public key "Maxim Dounin <mdounin@mdounin.ru>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
gpg: no ultimately trusted keys found

Now verify the signature:

[root@server]# gpg --trusted-key 0x520A9993A1C052F8 --verify nginx-1.12.2.tar.gz{.asc,}
gpg: Signature made Tue 17 Oct 2017 01:18:21 PM UTC using RSA key ID A1C052F8
gpg: key A1C052F8 marked as ultimately trusted
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: Good signature from "Maxim Dounin <mdounin@mdounin.ru>"

From here, configure nginx with the --add-module= option, pointing to the ModSecurity-nginx module that was previously downloaded:

[root@server]# tar -zxf nginx-1.12.2.tar.gz
[root@server]# cd nginx-1.12.2/
[root@server]# ./configure --add-module=/root/ModSecurity-nginx

Finally, build and install nginx:

[root@server]# make && make install

Configuring libmodsecurity in nginx

Adding libmodsecurity rules and configuration directives inside nginx configs is straightforward. Add the following to the nginx configuration:

modsecurity on;
modsecurity_rules '
    SecRuleEngine On
    SecDebugLog /tmp/modsec_debug.log
    SecDebugLogLevel 9
    SecRule ARGS "@streq test" "id:1,phase:1,deny,msg:\'test rule\'"
';

These directives can be added inside the http block, or one or more server or location blocks. Once this is added, reload nginx. This rule can now be tested by sending a regular request to nginx and examining the output:

[root@server]# curl -D - -s -o /dev/null localhost/
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Wed, 13 Jul 2016 18:06:15 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Wed, 13 Jul 2016 18:01:34 GMT
Connection: keep-alive
ETag: "578681fe-264"
Accept-Ranges: bytes

The single rule added via the modsecurity_rules directive will deny requests that have the word test inside a GET or POST argument. This can be seen by changing the curl test:

[root@server]# curl -D - -s -o /dev/null localhost/?a=test
HTTP/1.1 403 Forbidden
Server: nginx/1.10.1
Date: Wed, 13 Jul 2016 18:06:19 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

A 403 response means that nginx has blocked the request based on processing the request with libmodsecurity. From here, libmodsecurity can be customized using the available directives for ModSecurity (see the ModSecurity reference manual below for more information).

Final Notes

It should be noted that libmodsecurity is still in active development, so certain functionality is subject to change. As with any actively developed open source project, be sure to check the source code for the most recent releases.

Did this article answer your questions?

Article last updated PST.