NGINX Documentation

Administration Guide

Welcome to NGINX App Protect.

Overview

NGINX App Protect provides web application firewall (WAF) security protection for your web applications, including OWASP Top 10; response inspection; Meta characters check; HTTP protocol compliance; evasion techniques; disallowed file types; JSON & XML well-formedness; sensitive parameters & Data Guard.

This guide explains how to deploy NGINX App Protect as well as upgrade App Protect and the App Protect signature sets.

Prerequisites

NGINX App Protect is available to customers as a downloadable dynamic module at an additional cost. To purchase or add NGINX App Protect to an existing NGINX Plus subscription, contact the NGINX sales team.

NGINX Plus Release 19 and later supports NGINX App Protect.

NGINX App Protect supports the following operating systems:

  • CentOS 7.4.x and above
  • Debian 9 (Stretch)

The NGINX App Protect package has 4 dependencies:

  1. nginx-plus-module-appprotect - NGINX Plus dynamic module for App Protect
  2. app-protect-engine - The App Protect enforcement engine
  3. app-protect-plugin - The App Protect connector API between the engine and the NGINX Plus dynamic module
  4. app-protect-compiler - The App Protect enforcement engine compiler agent

See the NGINX Plus full list of prerequisites for more details. NGINX App Protect can be installed as a module to an existing NGINX Plus installation or as a complete NGINX Plus with App Protect installation in a clean environment.

Platform Security Considerations

When deploying App Protect on NGINX Plus take the following precautions to secure the platform. This avoids the risk of causing a Denial of Service condition or compromising the platform security.

  • Restrict permissions to the files on the NGINX App Protect platform to user nginx and group nginx, especially for the sensitive areas containing the configuration.
  • Remove unnecessary remote access services on the platform.
  • Configure a Syslog destination on the same machine as App Protect and proxy to an external destination. This avoids eavesdropping and man-in-the-middle attacks on the Syslog channel.

CentOS 7.4 Installation

  1. If you already have NGINX packages in your system, back up your configs and logs:

    sudo cp -a /etc/nginx /etc/nginx-plus-backup
    sudo cp -a /var/log/nginx /var/log/nginx-plus-backup
    
  2. Create the /etc/ssl/nginx/ directory:

    sudo mkdir -p /etc/ssl/nginx
    
  3. Log in to the NGINX Customer Portal and download the following two files:

    nginx-repo.key
    nginx-repo.crt
    
  4. Copy the above two files to the CentOS server’s /etc/ssl/nginx/ directory. Use an SCP client or another secure file transfer tool to perform this task.

  5. Install prerequisite packages:

    sudo yum install ca-certificates epel-release wget
    
  6. Add NGINX Plus repository by downloading the file nginx-plus-7.repo to /etc/yum.repos.d:

    sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/nginx-plus-7.repo
    
  7. Install the most recent version of the NGINX Plus App Protect package (which includes NGINX Plus):

    sudo yum install app-protect
    

    Alternatively, you can use the following command to list available versions:

    sudo yum --showduplicates list app-protect
    

    Then, install a specific version from the output of command above. For example:

    sudo yum install app-protect-20+2.52.1
    
  8. Check the NGINX binary version to ensure that you have NGINX Plus installed correctly:

    sudo nginx -v
    
  9. Load the NGINX App Protect module on the main context in the nginx.conf:

    load_module modules/ngx_http_app_protect_module.so;
    
  10. Enable NGINX App Protect on an http/server/location context in the nginx.conf file:

    app_protect_enable on;
    
  11. Configure SELinux as appropriate per your organization’s security policies. For example: (From: https://www.nginx.com/blog/using-nginx-plus-with-selinux/)

    sudo setenforce 0
    

    Note: The above command will temporarily globally disable SELinux. Refer to https://wiki.centos.org/HowTos/SELinux for additional information and practices related to this security mechanism.

  12. Start the NGINX service:

    sudo systemctl start nginx
    

Debian 9 Installation

  1. If you already have NGINX packages in your system, back up your configs and logs:

    sudo cp -a /etc/nginx /etc/nginx-plus-backup
    sudo cp -a /var/log/nginx /var/log/nginx-plus-backup
    
  2. Create the /etc/ssl/nginx/ directory:

    sudo mkdir -p /etc/ssl/nginx
    
  3. Log in to NGINX Customer Portal and download the following two files:

    nginx-repo.key
    nginx-repo.crt
    
  4. Copy the above two files to the Debian server’s /etc/ssl/nginx/ directory. Use an SCP client or another secure file transfer tool to perform this task.

  5. Install apt utils:

    sudo apt-get install apt-transport-https lsb-release ca-certificates wget
    
  6. Download and add the NGINX signing key:

    sudo wget http://nginx.org/keys/nginx_signing.key && sudo apt-key add nginx_signing.key
    
  7. Add NGINX Plus repository by downloading the file nginx-plus-7.repo to /etc/yum.repos.d:

    printf "deb https://plus-pkgs.nginx.com/debian `lsb_release -cs` nginx-plus\n" | sudo tee /etc/apt/sources.list.d/nginx-plus.list
    
  8. Download the apt configuration to /etc/apt/apt.conf.d:

    sudo wget -P /etc/apt/apt.conf.d https://cs.nginx.com/static/files/90nginx
    
  9. Update the repository and install the most recent version of the NGINX Plus App Protect package (which includes NGINX Plus):

    sudo apt-get update
    sudo apt-get install app-protect
    

    Alternatively, to install a specific version you should modify the repository URL in the /etc/apt/sources.list.d/nginx-plus.list file in the following way:

    deb https://plus-pkgs.nginx.com/Rxx/debian ...
    

    where xx is a release number.

    For example, to install app-protect version 20 make sure of the following:

    cat /etc/apt/sources.list.d/nginx-plus.list
    deb https://plus-pkgs.nginx.com/R20/debian stretch nginx-plus
    

    Then, use the following commands to update and list available versions:

     sudo apt-get update
     sudo apt-cache policy app-protect
    

    Finally, install a specific version from the output of command above. For example:

    sudo apt-get install app-protect=20+2.52.1-1~stretch
    
  10. Check the NGINX binary version to ensure that you have NGINX Plus installed correctly:

    sudo nginx -v
    
  11. Load the NGINX App Protect module on the main context in the nginx.conf file:

    load_module modules/ngx_http_app_protect_module.so;
    
  12. Enable NGINX App Protect on an http/server/location context in the nginx.conf via:

    app_protect_enable on;
    
  13. Start the NGINX service:

    sudo service nginx start
    

Docker Deployment

You need root permissions to perform this installation.

  1. Create a Dockerfile. In this example, CentOS 7.4 is used as the base Docker image.

    #For CentOS 7
    FROM centos:7.4.1708
    
    # Download certificate and key from the customer portal (https://cs.nginx.com)
    # and copy to the build context
    COPY nginx-repo.crt nginx-repo.key /etc/ssl/nginx/
    
    # Install prerequisite packages
    RUN yum -y install wget ca-certificates epel-release
    
    # Add NGINX Plus repo to yum
    RUN wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/nginx-plus-7.repo
    
    # Install NGINX App Protect
    RUN yum -y install app-protect \
        && yum clean all \
        && rm -rf /var/cache/yum \
        && rm -rf /etc/ssl/nginx
    
    # Forward request logs to Docker log collector
    RUN ln -sf /dev/stdout /var/log/nginx/access.log \
        && ln -sf /dev/stderr /var/log/nginx/error.log
        
    # Copy configuration files  
    COPY nginx.conf log-default.json /etc/nginx/
    COPY entrypoint.sh  ./
    
    CMD ["sh", "/entrypoint.sh"] 
    
  2. Log in to NGINX Plus Customer Portal and download your nginx-repo.crt and nginx-repo.key files.

  3. Copy the files to the directory where the Dockerfile is located.

  4. In the same directory create log-default.json.

    Note: NGINX App Protect uses the NGINX Plus logging. See the NGINX Plus logging for more details.

    {
       "filter":{
          "request_type":"all"
       }, 
       "content":{
          "format":"default",
          "max_request_size":"any",
          "max_message_size":"5k"
       }    
    }
    
  5. In the same directory create an nginx.conf file with the following contents:

    user nginx;
    
    worker_processes auto;
    load_module modules/ngx_http_app_protect_module.so;
    
    error_log /var/log/nginx/error.log debug;
    
    events {
        worker_connections 10240;
    }
    
    http {
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        sendfile on;
        keepalive_timeout 65;
    
        upstream app_backend_com {
            server 192.168.0.1:8000;
            server 192.168.0.1:8001;
        }
        server {
            listen 80;
            server_name app.example.com;
            proxy_http_version 1.1;
    
            app_protect_enable on;
            app_protect_security_log_enable on;
            app_protect_security_log "/etc/nginx/log-default.json" syslog:server=127.0.0.1:514;
    
            location / {
                client_max_body_size 0;
                default_type text/html;
                # set your backend here
                proxy_pass http://app_backend_com;
                proxy_set_header Host $host;
            }
        }
    }
    

    Important: Make sure replace upstream and proxy pass directives in this example.

  6. In the same directory create an entrypoint.sh file with the following contents:

    #!/usr/bin/env bash
    
    /bin/su -s /bin/bash -c '/opt/app_protect/bin/bd_agent &' nginx
    
    /bin/su -s /bin/bash -c "/usr/share/ts/bin/bd-socket-plugin tmm_count 4 proc_cpuinfo_cpu_mhz 2000000 total_xml_memory 307200000 total_umu_max_size 3129344 sys_max_account_id 1024 no_static_config 2>&1 > /var/log/app_protect/bd-socket-plugin.log &" nginx
    
    /usr/sbin/nginx -g 'daemon off;'
    
  7. Create a Docker image:

    docker build --no-cache -t app-protect .
    

    The --no-cache option tells Docker to build the image from scratch and ensures the installation of the latest version of NGINX Plus and NGINX App Protect. If the Dockerfile was previously used to build an image without the --no-cache option, the new image uses versions from the previously built image from the Docker cache.

  8. Verify that the app-protect image was created successfully with the docker images command:

    docker images app-protect
    
  9. Create a container based on this image, for example, my-app-protect container:

    docker run --name my-app-protect -p 80:80 -d app-protect
    
  10. Verify that the my-app-protect container is up and running with the docker ps command:

    docker ps
    

Post-Installation Checks

You can run the following commands to ensure that NGINX App Protect enforcement is operational.

  1. Check that the four processes needed for NGINX App Protect are running using ps aux:

    • bd_agent
    • bd-socket-plugin
    • nginx: master process
    • nginx: worker process
    USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root         7  1.2  0.3 128136 50440 ?        S    09:11   0:02 /usr/bin/perl /opt/app_protect/bin/bd_agent
    root         8  1.3  2.4 3486948 399092 ?      Sl   09:11   0:02 /usr/share/ts/bin/bd-socket-plugin tmm_count 4 proc_cpuinfo_cpu_mhz 2000000 total_xml_memory 307200000 total_umu_max_size 3129344 sys_max_account_id 1024 no_static_config
    root        14  0.0  0.1  71060 26680 ?        S    09:11   0:00 nginx: master process /usr/sbin/nginx -c /tmp/policy/test_nginx.conf -g daemon off;
    root        26  0.0  0.3  99236 52092 ?        S    09:12   0:00 nginx: worker process
    root        28  0.0  0.0  11788  2920 pts/0    Ss   09:12   0:00 bash
    root        43  0.0  0.0  47460  3412 pts/0    R+   09:14   0:00 ps aux
    
  2. Verify that there are no NGINX error.log errors and that the policy compiled successfully.

    2020/05/10 13:21:04 [notice] 402#402: APP_PROTECT { "event": "configuration_load_start", "configSetFile": "/opt/f5waf/config/config_set.json" }
    2020/05/10 13:21:04 [notice] 402#402: APP_PROTECT policy 'app_protect_default_policy' from: /etc/nginx/NginxDefaultPolicy.json compiled successfully
    2020/05/10 13:21:04 [notice] 402#402: APP_PROTECT { "event": "configuration_load_success", "software_version": "1.1.1", "attack_signatures_package":{"revision_datetime":"2019-07-16T12:21:31Z"},"completed_successfully":true}
    2020/05/10 13:21:04 [notice] 402#402: using the "epoll" event method
    2020/05/10 13:21:04 [notice] 402#402: nginx/1.17.6 (nginx-plus-r20)
    2020/05/10 13:21:04 [notice] 402#402: built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
    2020/05/10 13:21:04 [notice] 402#402: OS: Linux 3.10.0-957.27.2.el7.x86_64
    2020/05/10 13:21:04 [notice] 402#402: getrlimit(RLIMIT_NOFILE): 1048576:1048576
    2020/05/10 13:21:04 [notice] 406#406: start worker processes
    2020/05/10 13:21:04 [notice] 406#406: start worker process 407
    
  3. Check that sending an attack signature in a request returns a response block page containing a support ID.

    Request:
    http://10.240.185.211/?a=<script>
    
    Response:
    The requested URL was rejected. Please consult with your administrator.
    
    Your support ID is: 9847191526422998597
    
    [Go Back]
    
  4. If there are additional problems, collect the troubleshooting information in a tarball and send it to your customer support engineer.

    1. Tarball preparation to collect data for troubleshooting:

      • Get all versions via: rpm -qa nginx-plus* app-protect* > rpm_versions.txt
      • Get OS via: cat /etc/os-release > system_version.txt && uname -r >> system_version.txt && cat /proc/version >> system_version.txt
    2. Create a list of files for tarball in a file called logs.txt: rpm_versions.txt system_version.txt /var/log/app_protect/* (all app protect files) /var/log/nginx/* (all NGINX files)

    3. Add all nginx-app-protect policies and log file configuration

    4. Add all nginx configuration including all references such as /etc/nginx/nginx.conf

    5. Create the tarball:

      tar cvfz logs.tgz `cat logs.tx` 
      
    6. Send logs.tgz to support.

Updating App Protect Attack Signatures

Attack Signatures updates are released at higher frequency than App Protect, therefore they are released in their own package, separate from the App Protect package. You can update the attack signatures without updating the App Protect release, and conversely, you can update App Protect without changing the attack signature package, unless you move to a new NGINX Plus release.

Attack Signatures Package

The attack signature package is named: app-protect-attack-signatures. The version number for this package reflects the date the package was released. The format is: YYYY.MM.DD where:

  • YYYY is the 4-digit year
  • MM is the month
  • DD is the day in the month

Example: 2020.03.31

Compatibility with NGINX Plus Releases

A signature update file is compatible with the NGINX Plus release supported during the time the signature file was released and with all future releases from that point in time on. In other words, it is not compatible with earlier App Protect releases. Those older releases are not supported anyway at this point in time so you will have to upgrade App Protect to benefit from the support which includes Attack Signature updates.

For example, if Attack Signature update 2020.03.31 was released during the lifetime of NGINX Plus R21, then the supported releases are the two previous supported releases, R20 and R19, and then R21 and any release after that: R22, R23 and so on.

Installing Attack Signature Update

The App Protect installation comes with a built-in Attack Signature package that is not necessarily the most recent one and even if you have the most up to date Attack Signatures installed, updates are released every month or two, so you might want to update your Signatures from time to time. You can upgrade the signatures by updating the package any time after installing App Protect. We recommend you upgrade to the latest signature version right after installing App Protect.

After having updated the Attack Signature package you have to reload the configuration in order for the new version of the Signatures to take effect. Until then App Protect will run with the old version. That is useful when creating an environment with a specific tested version of the Attack Signatures.

CentOS

  1. To add NGINX Plus App Protect signatures repository, download the file app-protect-signatures-7.repo to /etc/yum.repos.d:

    sudo wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/app-protect-signatures-7.repo
    
  2. Update attack signatures:

    sudo yum install app-protect-attack-signatures
    

    To install a specific version, list the available versions:

    sudo yum --showduplicates list app-protect-attack-signatures
    

    To upgrade to a specific version:

    sudo yum install app-protect-attack-signatures-2020.04.30
    

    To downgrade to a specific version:

    sudo yum downgrade app-protect-attack-signatures-2019.07.16
    

Debian 9

  1. Add NGINX Plus App Protect signatures repository:

    printf "deb https://app-protect-sigs.nginx.com/debian/ `lsb_release -cs` nginx-plus\n" | sudo tee /etc/apt/sources.list.d/app-protect-sigs.list
    
  2. Download and add the NGINX Plus App Protect signatures signing key:

    sudo wget https://nginx.org/keys/app-protect-sigs.key && sudo apt-key add app-protect-sigs.key
    
  3. Download the apt configuration to /etc/apt/apt.conf.d:

    sudo wget -P /etc/apt/apt.conf.d https://cs.nginx.com/static/files/90app-protect-sigs
    
  4. Update attack signatures:

    sudo apt-get update && sudo apt-get install app-protect-attack-signatures
    

    To install a specific version, list the available versions:

    sudo apt-cache policy app-protect-attack-signatures
    

    Install a specific version:

    sudo apt-get install app-protect-attack-signatures=2020.04.30-1~stretch
    

Attack Signatures when Upgrading App Protect

Upgrading App Protect does not install new Attack Signatures. You will get the same Attack Signature release after upgrading App Protect. If you want to also upgrade the Attack Signatures, you will have to explicitly update them by the respective command above.

Upgrading App Protect

You can upgrade to the latest NGINX Plus and App Protect versions by downloading and installing the latest NGINX App Protect package. When upgrading from this package, App Protect will be uninstalled and reinstalled. The old default security policy is deleted and the new default security policy is installed. If you have created a custom security policy, the policy persists and you will need to update nginx.conf and point to the custom security policy by referencing the json file (using the full path).

If you upgrade your NGINX version outside of the App Protect module, App Protect will be uninstalled and you will need to reinstall it. You need to restart NGINX after an upgrade.