How to Secure Nginx with Naxsi Firewall on Ubuntu 20.04 VPS

Last updated: March 8th 2024

Introduction

Nginx is one of the most popular and high-performance web servers in the world. So it is very important part of any system administrator to increase the security of the Nginx server. Naxsi "Nginx Anti XSS & SQL Injection" is a free, open-source and high-performance web application firewall that can be used to protect your webserver against different types of attacks like SQL Injections and Cross-Site Scripting. Naxsi works by detecting unexpected characters in the HTTP GET and POST requests.

In this tutorial, we will show you how to install and configure Naxsi firewall to protect the Nginx server on Ubuntu 20.04 server.

Please note: Doing these actions will temporarily bring down your server. Do not do this on a live site. If you want to add Naxsi to a live server, create a new server from a snapshot and test this out - then migrate your changes back to your live server once you've verified everything is working.

This guide may not work with latest versions of Nginx and Naxsi. Moreover, Naxsi is not longer maintained. So it's not recommended to use it. If you're a Webdock customer, as an alernative, look at our Botguard addon.

Prerequisites

Getting Started

Before starting, it is recommended to update your system's package to the latest version. You can update them with the following commands:

apt-get update -y
apt-get upgrade -y

 

Once all the packages are updated, restart your server to apply all the configuration changes.

Next, you will need to install all the dependencies required to install Naxsi. You can install all of them with the following command:

apt-get install zlib1g zlib1g-dev build-essential bzip2 unzip libpcre3-dev libssl-dev libgeoip-dev wget unzip libxslt-dev libgd-dev -y

Once all the dependencies are installed, you can proceed to the next step.

Compile Nginx with Naxsi Support

By default, Nginx is pre-installed in Webdock Ubuntu 20.04 instance. But, Naxsi is a third-party Nginx module that does not comes with Nginx package.
So, you will need to download Nginx and Naxsi source, and compile Nginx with Naxsi support.

First, check the installed version of Nginx on your Webdock instance with the following command:

nginx -v

Output:

nginx version: nginx/1.19.6


Once you get the Nginx version, go to the Nginx official website and download the same Nginx version with the following command:

wget http://nginx.org/download/nginx-1.19.6.tar.gz

Next, download the latest version of Naxsi with the following command:

wget https://github.com/nbs-system/naxsi/archive/master.zip

Next, extract the downloaded source file with the following commands:

tar -xvzf nginx-1.19.6.tar.gz
unzip master.zip

 

Before recompiling Nginx, you will also need to find all the installed Nginx modules in the system.
You can list them with the following command:

nginx -V

You should see the output similar to the following:

nginx version: nginx/1.19.6
built by gcc 9.3.0 (Ubuntu 9.3.0-10ubuntu2) 
built with OpenSSL 1.1.1f  31 Mar 2020 (running with OpenSSL 1.1.1i  8 Dec 2020)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.19.6/debian/debuild-base/nginx-1.19.6=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

Next, stop the running Nginx service with the following command:

systemctl stop nginx

Next, copy the output from the "nginx -V" command as shown in the above output and append it to ./configure command, add new arguement --add-module=/root/naxsi-master/naxsi_src/ and --sbin-path=/usr/sbin/nginx and add ./configure at the beginning of configure arguements.

After making all the changes, copy these commands and run on the terminal as shown below:

cd nginx-1.19.6
./configure --add-module=/root/naxsi-master/naxsi_src/ --sbin-path=/usr/sbin/nginx --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.19.6/debian/debuild-base/nginx-1.19.6=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

 

Next, run the make command to run a series of tasks defined in the Makefile:

make

Next, run the make install command to copy all the configuration files to their correct location:

make install

Once the above command runs successfully that means Nginx has been recompiled with Naxsi support.

Next, start the Nginx service with the following command:

systemctl start nginx

You can verify the Nginx service status with the following command:

systemctl status nginx

If everything goes fine, you should get the following output:

● nginx.service - nginx - high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2021-02-08 12:14:07 UTC; 6s ago
       Docs: http://nginx.org/en/docs/
    Process: 11179 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
   Main PID: 11180 (nginx)
      Tasks: 397 (limit: 464185)
     Memory: 28.0M
     CGroup: /system.slice/nginx.service
             ├─11180 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
             ├─11181 nginx: worker process
             ├─11182 nginx: worker process
             ├─11183 nginx: worker process
             ├─11184 nginx: worker process
             ├─11185 nginx: worker process
             ├─11186 nginx: worker process
             ├─11187 nginx: worker process
             ├─11188 nginx: worker process
             ├─11189 nginx: worker process
             ├─11208 nginx: worker process
             ├─11233 nginx: worker process
             └─11264 nginx: worker process

Feb 08 12:14:07 ubuntu2004 systemd[1]: Starting nginx - high performance web server...
Feb 08 12:14:07 ubuntu2004 systemd[1]: Started nginx - high performance web server.

Configure Naxsi

Naxsi comes with a set of core rules that can be used to determine how requests are blocked from the server. So, you will need to copy Naxsi core rules to the Nginx configuration directory. You can copy them from Naxsi source directory with the following command:

cp -r /root/naxsi-master/naxsi_config/naxsi_core.rules /etc/nginx/

Next, you will need to enable Naxsi rules and define different types of attacks that can be blocked by Naxsi. You can do it by creating naxsi.rules file:

nano /etc/nginx/naxsi.rules

Add the following lines:

SecRulesEnabled;
DeniedUrl "/error.html";

## Check Naxsi rules
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;

Save and close the file when you are finished.

Next, you will need to create an error.html file to redirected blocked requests to error.html file. Place this in your web root as defined in your nginx configuration, on Webdock this is typically /var/www/html

nano /var/www/html/error.html

Make sure this file is owned by a user and group which belongs to your web server, typically www-data, or you will get a 403 forbidden response instead of the browser showing the block message - to change ownership of the file, execute:

chown www-data:www-data /var/www/html/error.html

Add the following lines:

<html>
<head>
<title>Blocked By NAXSI</title>
</head>
<body>
<div style="text-align: center">
<h1>Malicious Request</h1>
<hr>
<p>This Request Has Been Blocked By NAXSI.</p>
</div>
</body>
</html>

Save and close the file. Then, configure Nginx server to include Naxsi rules by editing nginx.conf file:

nano /etc/nginx/nginx.conf

Add the following lines within http {} section:

include /etc/nginx/naxsi_core.rules;

Save and close the file.

Next, create or edit an existing Nginx virtual host file and include naxsi.rules. You will need to include naxsi.rules file in each virtual host that you want to enable Naxsi.

nano /etc/nginx/sites-available/webdock.conf

Add highlighted line to your location / {} block:

server {
listen 80;

root /usr/share/nginx/html;
index index.html index.htm;

# Make site accessible from http://localhost/
server_name 45.148.29.27;

location / {
include /etc/nginx/naxsi.rules;

try_files $uri $uri/ =404;

}

}

Save and close the file. Then, check Nginx for any syntax error with the following command:

nginx -t

If everything goes fine, you should get the following output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Next, enable the Nginx virtual host and remove the default virtual host with the following command:

ln -s /etc/nginx/sites-available/naxsi.conf /etc/nginx/sites-enabled/
rm -rf /etc/nginx/sites-enabled/webdock

Finally, restart Nginx service to apply all the configuration changes:

systemctl restart nginx


Test Naxsi Firewall

Naxsi firewall is now installed and configured, it's time to test it against SQLi and XSS attack.

To test Naxsi against XSS attack, open your web browser from the remote system and type the URL http://45.148.29.27/q?="><script>alert(1)</script> . As per the Naxsi rules which you have configured earlier, you should be redirected to the error.html page with the following message:

naxsi1.png

You can also verify this by checking Nginx log as shown below:

tail -f /var/log/nginx/error.log

You should see that XSS request from the remote host has been blocked by Naxsi firewall:

2021/02/08 11:52:04 [notice] 1186#1186: signal process started
2021/02/08 11:52:08 [notice] 1611#1611: signal process started
2021/02/08 11:52:31 [notice] 2454#2454: signal process started
2021/02/08 11:52:32 [notice] 2851#2851: signal process started
2021/02/08 12:19:20 [error] 12018#12018: *1 NAXSI_FMT: ip=106.213.237.134&server=45.148.29.27&uri=/q&vers=1.3&total_processed=2&total_blocked=1&config=block&cscore0=$SQL&score0=8&cscore1=$XSS&score1=8&zone0=ARGS&id0=1001&var_name0=, client: 106.213.237.134, server: 45.148.29.27, request: "GET /q?=%22%3E%3Cscript%3Ealert(1)%3C/script%3E HTTP/1.1", host: "45.148.29.27"

To test Naxsi against SQLi attack, open your web browser from the remote system and type the URL http://45.148.29.27/?q=1" or "1"="1". You should get the same message as shown in the following page:

naxsi1.png

You can also check the Nginx server log again with the following command:

tail -f /var/log/nginx/error.log

You should get the same message as shown below:

2021/02/08 12:19:20 [error] 12018#12018: *1 NAXSI_FMT: ip=106.213.237.134&server=45.148.29.27&uri=/q&vers=1.3&total_processed=2&total_blocked=1&config=block&cscore0=$SQL&score0=8&cscore1=$XSS&score1=8&zone0=ARGS&id0=1001&var_name0=, client: 106.213.237.134, server: 45.148.29.27, request: "GET /q?=%22%3E%3Cscript%3Ealert(1)%3C/script%3E HTTP/1.1", host: "45.148.29.27"
2021/02/08 12:23:32 [error] 12018#12018: *3 NAXSI_FMT: ip=106.213.237.134&server=45.148.29.27&uri=/&vers=1.3&total_processed=3&total_blocked=2&config=block&cscore0=$SQL&score0=40&cscore1=$XSS&score1=40&zone0=ARGS&id0=1001&var_name0=q, client: 106.213.237.134, server: 45.148.29.27, request: "GET /?q=1%22%20or%20%221%22=%221%22 HTTP/1.1", host: "45.148.29.27"

 

Congratulations! you have successfully setup Naxsi firewall to protect Nginx server against malicious attacks. Your Nginx webserver is now secured from XSS and SQL injection attack. For more information, you can visit the Naxsi official documentation at Naxsi Doc.

Related articles