How to install and configure Nginx ModSecurity on Centos 8

How to install and configure Nginx ModSecurity on Centos 8

ModSecurity is an open source and great module to securing sites against Layer 7 attacks.

Nginx ModSecurity will prevent SQL injection (SQLi), local file inclusion (LFI), and cross‑site scripting (XSS).

Getpagespeed.com already release repository for CentOS 8, however after they activated Centos 7 repository, we wont use on CentOS 8.

First we need to install Nginx from CentOS 8 repository then upgrade using own compiled Nginx.

# dnf install nginx

Then check nginx version

# nginx -V

The output is like this

# nginx -V
nginx version: nginx/1.14.1
built by gcc 8.2.1 20180905 (Red Hat 8.2.1-3) (GCC)
built with OpenSSL 1.1.1 FIPS  11 Sep 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'

The problem is Nginx version too low 1.14.1. On latest CentOS 7, official Nginx version is 1.16.1.

Lets download and compile Nginx 1.16.1 with module security. We will try to same configure arguments as official from CentOS 8.

# dnf group install "Development Tools"
# dnf install pcre-devel libxslt-devel gd-devel libcurl-devel ssdeep-libs ssdeep-devel lua lua-devel libxml2-devel yajl-devel lmdb-devel lmdb-libs lmdb xz-devel GeoIP-devel GeoIP-GeoLite-data gd-devel
# ./configure --add-dynamic-module=../ModSecurity-nginx --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/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/lib/nginx/client_temp --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --http-scgi-temp-path=/var/lib/nginx/scgi --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-http_perl_module=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
# make

Backup /usr/sbin/nginx to /usr/sbin/nginx-1.14.1

# mv /usr/sbin/nginx /usr/sbin/nginx-1.14.1
# cp objs/nginx /usr/sbin/nginx
# cp objs/ngx_http_modsecurity_module.so /usr/lib64/nginx/modules
# cp objs/ngx_http_perl_module.so /usr/lib64/nginx/modules
# cp objs/ngx_http_image_filter_module.so /usr/lib64/nginx/modules
# cp objs/ngx_http_xslt_filter_module.so /usr/lib64/nginx/modules
# cp objs/ngx_mail_module.so /usr/lib64/nginx/modules
# cp objs/ngx_stream_module.so /usr/lib64/nginx/modules
# cp /usr/src/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsecurity.conf
# cp /usr/src/ModSecurity/unicode.mapping /etc/nginx/unicode.mapping

Enable SecRuleEngine, edit /etc/nginx/modsecurity.conf and change

SecRuleEngine DetectionOnly
to
SecRuleEngine On

Check nginx version should be like this

# nginx -V
nginx version: nginx/1.16.1
built by gcc 8.2.1 20180905 (Red Hat 8.2.1-3) (GCC)
built with OpenSSL 1.1.1 FIPS  11 Sep 2018
TLS SNI support enabled
configure arguments: .........

Disable Nginx update by edit /etc/dnf/dnf.conf by adding this code

exclude=nginx*

Configure Nginx to use ModSecurity module

To load ModSecurity on Nginx, edit /etc/nginx/nginx.conf and add this code in top of configuration.

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

load_module modules/ngx_http_modsecurity_module.so;

And on your server block add this code:

server {
	.......
	.......
	modsecurity on;
	modsecurity_rules_file /etc/nginx/modsec_includes.conf;
	.......
	.......
}

Get OWASP ModSecurity Core Rule Set (CRS) from https://coreruleset.org or https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project

# cd /etc/nginx
# wget https://github.com/SpiderLabs/owasp-modsecurity-crs/archive/v3.2.0.zip
# unzip v3.2.0.zip
# mv owasp-modsecurity-crs-3.2.0 owasp-modsecurity-crs
#### OR BY CLONE
# git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git
# cp owasp-modsecurity-crs/crs-setup.conf.example owasp-modsecurity-crs/crs-setup.conf

Create /etc/nginx/modsec_includes.conf and add code below

include modsecurity.conf
include /etc/nginx/owasp-modsecurity-crs/crs-setup.conf
include /etc/nginx/owasp-modsecurity-crs/rules/*.conf

# Additional custom rules here
SecRule REQUEST_URI "@beginsWith /rss/" "phase:1,t:none,pass,id:'26091902',nolog,ctl:ruleRemoveById=200002"

Check your Nginx configuration with

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

If no problem, start Nginx

# systemctl restart nginx

Testing Nginx ModSecurity

Check on your rules for blacklist user agent, for Comodo rules is bl_agents

# curl -I -H "User-Agent: floodgate" https://serverdiary.com

Example response:

# curl -I -H "User-Agent: floodgate" https://serverdiary.com
HTTP/1.1 403 Forbidden
Server: nginx
Date: Sat, 26 Oct 2019 18:07:01 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive

One thought on “How to install and configure Nginx ModSecurity on Centos 8

  1. There are some lines missing, i.e. inside which directory you are running ./configure… command?

Leave a Reply

Your email address will not be published. Required fields are marked *