This article explains how to install the NGINX Plus with ModSecurity web application firewall (WAF), configure a simple rule, and set up logging.

Table of Contents

Overview

NGINX Plus Release 12 and later supports the NGINX Plus with ModSecurity web application firewall (WAF). The ModSecurity WAF protects web applications against various Layer 7 attacks; provides DDoS mitigation, real‑time blacklisting, and audit logging; and enables PCI‑DSS 6.6 compliance.

This chapter explains how to install the ModSecurity WAF, presents a sample configuration with a simple rule, and sets up logging. For information about rule sets, see:

Prerequisites

The ModSecurity WAF is available to NGINX Plus customers as a downloaded dynamic module at an additional cost. To purchase or start a free trial of NGINX Plus with the ModSecurity WAF, or add the ModSecurity WAF to an existing NGINX Plus subscription, contact the NGINX sales team.

Installing the ModSecurity WAF

To install the dynamic module for the ModSecurity WAF, perform the following steps.

  1. Use the OS package‑management utility to install the dynamic module from the NGINX Plus module repository. The following command is appropriate for Debian and Ubuntu systems. For systems that use RPM packages, substitute the yum install command.

    $ sudo apt-get install nginx-plus-module-modsecurity
  2. Add the following line in the top‑level (“main”) context of /etc/nginx/nginx.conf :

    load_module modules/ngx_http_modsecurity_module.so;
  3. Run the following command to verify that the module loads successfully, as confirmed by the indicated output:

    $ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful

Example: Configuring the ModSecurity WAF with a Simple Rule

In this example we configure a simple ModSecurity rule to block certain requests to a demo application. NGINX Plus acts as the reverse proxy in the example, but the same configuration applies to load balancing. The demo application is simply an NGINX Plus virtual server that returns status code 200 and a text message. It serves as the demo application in the chapters about using rule sets with the ModSecurity WAF as well.

Creating the Demo Web Application

Create the demo web application by configuring a virtual server in NGINX Plus.

  1. Create the file /etc/nginx/conf.d/echo.conf with the following content. It configures a “web server” that listens on localhost port 8085 and returns status code 200 and a message containing the requested URI.

    server {
    listen localhost:8085;

    location / {
    default_type text/plain;
    return 200 "Thank you for requesting ${request_uri}\n";
    }
    }

  2. Test the application by reloading the NGINX Plus configuration and making a request.

    $ sudo nginx -s reload
    $ curl -D - http://localhost:8085
    HTTP/1.1 200 OK
    Server: nginx/1.11.10
    Date: Wed, 3 May 2017 08:55:29 GMT
    Content-Type: text/plain
    Content-Length: 27
    Connection: keep-alive

    Thank you for requesting /

Configuring NGINX Plus as a Reverse Proxy

Configure NGINX Plus as a reverse proxy for the demo application.

  1. Create the file /etc/nginx/conf.d/proxy.conf with the following content. It configures a virtual server that listens on port 80 and proxies all requests to the demo application.

    server {
    listen 80;

    location / {
    proxy_pass http://localhost:8085;
    proxy_set_header Host $host;
    }
    }

    Note: If any other virtual servers (server blocks) in your NGINX Plus configuration listen on port 80, you need to disable them for the reverse proxy to work correctly. For example, the /etc/nginx/conf.d/default.conf file provided in the nginx‑plus package includes such a server block. Comment out or remove the server block, but do not remove or rename the default.conf file itself – if the file is missing during an upgrade, it is automatically restored, which can break the reverse‑proxy configuration.

  2. Reload the NGINX Plus configuration.

    $ sudo nginx -s reload
  3. Verify that a request succeeds, which confirms that the proxy is working correctly.

    $ curl -D - http://localhost
    HTTP/1.1 200 OK
    Server: nginx/1.11.10
    Date: Wed, 3 May 2017 08:58:02 GMT
    Content-Type: text/plain
    Content-Length: 27
    Connection: keep-alive

    Thank you for requesting /

Protecting the Demo Web Application

Configure the ModSecurity WAF to protect the demo web application by blocking certain requests.

  1. Create the folder /etc/nginx/modsec for storing ModSecurity configuration:

    $ sudo mkdir /etc/nginx/modsec
  2. Download the file of recommended ModSecurity configuration from the v3/master branch of the ModSecurity GitHub repo and name it modsecurity.conf:

    $ cd /etc/nginx/modsec
    $ sudo wget https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended
    $ sudo mv modsecurity.conf-recommended modsecurity.conf
  3. Enable execution of rules by commenting out the existing SecRuleEngine directive in modsecurity.conf and adding the indicated directive. We will define the sample rule in the next step.

    # SecRuleEngine DetectionOnly
    SecRuleEngine On

    For more information about the SecRuleEngine directive, see the ModSecurity documentation.

  4. Create the main ModSecurity WAF configuration file, /etc/nginx/modsec/main.conf, and define a rule in it:

    # Include the recommended configuration
    Include /etc/nginx/modsec/modsecurity.conf

    # A test rule
    SecRule ARGS:testparam "@contains test" "id:1234,deny,log,status:403"

    • Include – Includes the recommended configuration from the modsecurity.conf file.
    • SecRule – Creates a rule that protects the application by blocking requests and returning status code 403 when the testparam parameter in the query string contains the string test.

    For more information about the SecRule directive, see the ModSecurity documentation.

  5. Change the reverse proxy configuration file (/etc/nginx/conf.d/proxy.conf) to enable the ModSecurity WAF:

    server {
    listen 80;

    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsec/main.conf;

    location / {
    proxy_pass http://localhost:8085;
    proxy_set_header Host $host;
    }
    }

    • modsecurity on – Enables the ModSecurity WAF.
    • modsecurity_rules_file – Specifies the location of the ModSecurity WAF configuration file.

    Documentation for modsecurity* directives in the NGINX Plus configuration file is available on GitHub.

  6. Reload the NGINX Plus configuration:

    $ sudo nginx -s reload
  7. Verify that the rule configured in Step 4 works correctly, by making a request that includes the string test in the value of the query string testparam parameter.

    $ curl -D - http://localhost/foo?testparam=thisisatestofmodsecurity
    HTTP/1.1 403 Forbidden
    Server: nginx/1.11.10
    Date: Wed, 3 May 2017 09:00:48 GMT
    Content-Type: text/html
    Content-Length: 170
    Connection: keep-alive

    <html>
    <head><title>403 Forbidden</title></head>
    <body bgcolor="white">
    <center><h1>403 Forbidden</h1></center>
    <hr/><center>nginx/1.11.10</center>
    </body>
    </html>

    The request returns status code 403, confirming that the WAF is enabled and executing the rule.

Setting Up Logging

By default, the ModSecurity WAF logs its activity to the NGINX Plus error log, at the warn level for blocked requests and the info level for other messages. The error_log directive in the main /etc/nginx/nginx.conf file provided with NGINX Plus is configured to write messages to /var/log/nginx/error.log at the warn level and higher. If you want to capture all messages from the ModSecurity WAF, you need to set the logging level to info instead.

error_log /var/log/nginx/error.log info;

Note: Your existing configuration might include definitions for multiple error logs, in files other than nginx.conf and placed in more specific contexts, such as a location block. Make sure to update all the relevant error_log directives.

For the blocked request from the previous section, the following message appears in the error log. The [id "1234"] field identifies the rule that blocked the request.

2017/04/26 09:00:48 [warn] 1504#1504: *5 [client 127.0.0.1] ModSecurity: Access denied with code 403 (phase 1). Matched "Operator `Contains' with parameter `test' against variable `ARGS:testparam' (Value: `thisisatestofmodsecurity' ) [file "/etc/nginx/modsec/main.conf"] [line "207"] [id "1234"] [rev ""] [msg ""] [data ""] [severity "0"] [ver ""] [maturity "0"] [accuracy "0"] [hostname "127.0.0.1"] [uri "/foo"] [unique_id "14931972481.000000"] [ref "o7,4v19,24"], client: 127.0.0.1, server: , request: "GET /foo?testparam=thisisatestofmodsecurity HTTP/1.1", host: "localhost"

Controlling Audit and Debug Logging

ModSecurity also supports audit logging as configured with the SecAudit* set of directives. Audit logging is enabled in the recommended configuration that we downloaded to /etc/nginx/modsec/modsecurity.conf (in Step 2 of Protecting the Demo Web Application), but we recommend disabling it in production environments, both because audit logging affects ModSecurity performance and because the log file can grow large very quickly and exhaust disk space. To disable audit logging, change the value of the SecAuditEngine directive in modsecurity.conf to off.

SecAuditEngine off

If you experience problems with the ModSecurity WAF, you can enable debug logging by changing the SecDebugLog and SecDebugLogLevel directives in modsecurity.conf to the following values. Like audit logging, debug logging generates a large volume of output and affects ModSecurity performance, so we recommend disabling it in production.

SecDebugLog /tmp/modsec_debug.log
SecDebugLogLevel 9

Limitations

Please be aware of the following limitations:

  • Rules that inspect the response body are not supported and are ignored if included in the configuration.
  • Inclusion of the request and response body in the audit log is not supported.

Conclusion

In this chapter, we installed the ModSecurity WAF for NGINX Plus, created a simple rule for quick testing, and set up logging of ModSecurity WAF activity.

The simple rule works correctly, but doesn’t provide any real protection to an application. See the following chapters for instructions on configuring rules for comprehensive application protection:

Resources