Overview
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@instance]# 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@instance]# 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@instance]# cd ModSecurity/ [root@instance]# git submodule init [root@instance]# git submodule update
Finally, configure, build, and install the libmodsecurity library:
[root@instance]# ./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@instance]# 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@instance]# 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@instance]# 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@instance]# 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@instance]# tar -zxf nginx-1.12.2.tar.gz [root@instance]# cd nginx-1.12.2/ [root@instance]# ./configure --add-module=/root/ModSecurity-nginx
Finally, build and install nginx:
[root@instance]# 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@instance]# 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@instance]# 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.