Installing LEMP with Nginx Security and Intrusion Prevention – Complete WordPress Hardening Guide – Part 2

In this tutorial we will install nginx , mariadb, php, and WordPress. We will also secure nginx from DoS and brute force attacks. Nginx security is already pretty good out of the box, and our CIS compliance hardening in step one has done a decent job have hardening the box. However we will add some addition nginx security, using fail2ban.

Also thanks to these sites for Nginx and fail2ban configuration

2.2 – Install Nginx

sudo apt install -y nginx

Install and Configure Maria DB to start at boot

sudo apt install -y mariadb-server 
sudo systemctl enable mariadb
sudo systemctl start mariadb

Setup WP Database

sudo mysql_secure_installation
mysql -u root -p

After logging into mysql run these commands. (changing user/pass of course}

CREATE DATABASE wp_db;
CREATE USER wpuser IDENTIFIED BY 'Passw0rd2';
GRANT ALL ON wp_db.* TO `wpuser`;
exit

Install Cerbot for SSL Certificate

sudo apt install python-certbot-nginx -y

Install PHP

sudo apt install -y php
sudo apt install -y php-pear php-fpm php-dev php-zip php-curl php-xmlrpc php-gd php-mysql php-mbstring php-xml libapache2-mod-php

Configure PHP for nginx

sudo sh -c "sed -i '/cgi.fix_pathinfo=1/c\cgi.fix_pathinfo=0' /etc/php/7.2/fpm/php.ini" 
sudo sh -c "echo '' >> /etc/php/7.2/fpm/php.ini"
sudo sh -c "echo '' >> /etc/php/7.2/fpm/php.ini"
sudo sh -c "echo ';***********************************************************' >> /etc/php/7.2/fpm/php.ini"
sudo sh -c "echo '; WordPress Settings ' >> /etc/php/7.2/fpm/php.ini"
sudo sh -c "echo ';***********************************************************' >> /etc/php/7.2/fpm/php.ini"
sudo sh -c "echo 'upload_max_filesize = 500M' >> /etc/php/7.2/fpm/php.ini"
sudo sh -c "echo 'post_max_size = 2000M' >> /etc/php/7.2/fpm/php.ini"
sudo sh -c "echo 'memory_limit = 2000M' >> /etc/php/7.2/fpm/php.ini"
sudo sh -c "echo 'max_execution_time = 120' >> /etc/php/7.2/fpm/php.ini"

Create nginx site file. Change mydomain.com to your domain

sudo sh -c "cat > /etc/nginx/sites-available/mydomain.com <<\EOF
server {
    listen 80;
    listen [::]:80;
    root /var/www/html;
    index  index.php index.html index.htm;
    server_name  mydomain.com www.mydomain.com;

    client_max_body_size 500M;

    location / {
        try_files \$uri \$uri/ /index.php?\$args;
    }
	
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        log_not_found off;
    }	

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }	

    location ~ \.php$ {
         include snippets/fastcgi-php.conf;
         fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
         fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
         include fastcgi_params;
    }
}
EOF
"

Configure Site as Enabled and link the configuration file

sudo sh -c "ln -s /etc/nginx/sites-available/mydomain.com /etc/nginx/sites-enabled/"
sudo sh -c "rm -f /etc/nginx/sites-available/default"
sudo sh -c "rm -f /etc/nginx/sites-enabled/default"


sudo systemctl restart nginx

Install WordPress

sudo sh -c "wget https://wordpress.org/latest.tar.gz -o /var/www/html/latest.tar.gz"
sudo sh -c "tar -zxvf latest.tar.gz -C /var/www/html/ --strip-components=1"
sudo sh -c "rm -rf /var/www/html/latest.tar.gz"
sudo sh -c "cp /var/www/html/wp-config-sample.php /var/www/html/wp-config.php"

Set Permissions for /var/www/html/

sudo chown -R www-data:www-data /var/www/html/*
sudo chmod -R 755 /var/www/html/*

Set WP Config (change username and password to match ones you created in mysql step)

sudo sh -c "sed -i '/database_name_here/c\define\( '\''DB_USER'\'', '\''wpuser'\'' \);' /var/www/html/wp-config.php" 
sudo sh -c "sed -i '/username_here/c\define\( '\''DB_NAME'\'', '\''wp_db'\'' \);' /var/www/html/wp-config.php" 
sudo sh -c "sed -i '/password_here/c\define\( '\''DB_PASSWORD'\'', '\''Passw0rd2'\'' \);' /var/www/html/wp-config.php" 

Configure SSL

Follow prompts. Select 2 to route ALL traffic through through your website. Other settings can be default.


note: make sure you have your DNS pointed to your domain at this point if you cannot ping mydomain.com and return your servers IP address, this step will fail and you will need to wait for DNS replication.

sudo certbot --nginx -m info@mydomain.com -d mydomain.com -d www.mydomain.com

Configure NGINX Security and SSH Intrusion Prevention by using Fail2ban

This configuration will mitigate brute forces and denial of service attacks.

Install Fail2ban for NGINX security

sudo apt install -y fail2ban

Configure Fail2ban to be enabled at boot

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Create new Fail2ban config file

sudo sh -c "touch /etc/fail2ban/jail.local"

Configure SSH Jail

sudo sh -c "echo "" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "# # SSH Jail Settings" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "[ssh]" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "enabled = true" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "port = ssh" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "filter = sshd" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "maxretry = 3 " >> /etc/fail2ban/jail.local"
sudo sh -c "echo "bantime = 600 " >> /etc/fail2ban/jail.local"
sudo sh -c "echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"

Configure NGINX Authentication Jail

sudo sh -c "echo "" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "# # Nginx Auth Jail Settings" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "[nginx-auth]" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "enabled = true" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "filter = nginx-auth" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "action = iptables-multiport[name=NoAuthFailures, port="http,https"]" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "logpath = /var/log/nginx*/*error*.log" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "bantime = 600 " >> /etc/fail2ban/jail.local"
sudo sh -c "echo "maxretry = 6" >> /etc/fail2ban/jail.local"
sudo sh -c "echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"

Add NGINX login jail

sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "# # Nginx Login Jail Settings" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "[nginx-login]" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "enabled = true" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "filter = nginx-login" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "action = iptables-multiport[name=NoLoginFailures, port="http,https"]" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "logpath = /var/log/nginx*/*access*.log" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "bantime = 600 " >> /etc/fail2ban/jail.local"
sudo sh -c"echo "maxretry = 6" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"

Add NGINX Jail for Bad Bots

sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "# # Nginx Bad Bots Jail Settings" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "[nginx-badbots]" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "enabled = true" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "filter = apache-badbots" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "action = iptables-multiport[name=BadBots, port="http,https"]" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "logpath = /var/log/nginx*/*access*.log" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "bantime = 86400 # 1 day" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "maxretry = 1" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"

Add NGINX Script Jail

sudo sh -c"echo "" >> /etc/fail2ban/jail.local
sudo sh -c"echo "" >> /etc/fail2ban/jail.local
sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "# # Nginx No Script Jail Settings" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local
sudo sh -c"echo "" >> /etc/fail2ban/jail.local
sudo sh -c"echo "[nginx-noscript]" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "enabled = true" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "filter = nginx-noscript" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "action = iptables-multiport[name=NoScript, port="http,https"]" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "logpath = /var/log/nginx*/*access*.log" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "bantime = 86400 # 1 day" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "maxretry = 6" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"

Add NGINX Proxy Jail

sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "# # Nginx No Proxy Jail Settings" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "[nginx-noproxy]" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "enabled = true" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "filter = nginx-noproxy" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "action = iptables-multiport[name=NoProxy, port="http,https"]" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "logpath = /var/log/nginx*/*access*.log" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "bantime = 86400 " >> /etc/fail2ban/jail.local"
sudo sh -c"echo "maxretry = 0" >> /etc/fail2ban/jail.local"
sudo sh -c"echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"

Create Proxy config file for jail

sudo sh -c "cat > /etc/fail2ban/filter.d/nginx-proxy.conf <<EOF
# Proxy filter /etc/fail2ban/filter.d/nginx-proxy.conf:
#
# Block IPs trying to use server as proxy.
#
# Matches e.g.
# 192.168.1.1 - - GET http://www.something.com/
[Definition]
failregex = ^<HOST> -.*GET http.*
ignoreregex =
EOF
"

Create NoScript config file for jail

sudo sh -c "cat > /etc/fail2ban/filter.d/nginx-noscript.conf <<EOF
# Noscript filter /etc/fail2ban/filter.d/nginx-noscript.conf:
#
# Block IPs trying to execute scripts such as .php, .pl, .exe and other funny scripts.
#
# Matches e.g.
# 192.168.1.1 - - GET /something.php
#
[Definition]
failregex = ^<HOST> -.*GET.*(\.php|\.asp|\.exe|\.pl|\.cgi|\scgi)
ignoreregex =
EOF
"

Create Authentication config file for jail

sudo sh -c "cat > /etc/fail2ban/filter.d/nginx-auth.conf <<EOF
# Auth filter /etc/fail2ban/filter.d/nginx-auth.conf:
#
# Blocks IPs that fail to authenticate using basic authentication
#
[Definition]
 
failregex = no user/password was provided for basic authentication.*client: <HOST>
            user .* was not found in.*client: <HOST>
            user .* password mismatch.*client: <HOST>
 
ignoreregex =
EOF
"

Create Login config file for jail

sudo sh -c "cat > /etc/fail2ban/filter.d/nginx-login.conf <<EOF
# Login filter /etc/fail2ban/filter.d/nginx-login.conf:
#
# Blocks IPs that fail to authenticate using web application's log in page
#
# Scan access log for HTTP 200 + POST /sessions => failed log in
[Definition]
failregex = ^<HOST> -.*POST /sessions HTTP/1\..\" 200
ignoreregex =
EOF
"

Restart Fail2ban

sudo systemctl restart fail2ban

All Done , but Stay Tuned!!

That’s it! LEMP and WordPress are now configured on the server. We have also setup fail2ban jail for SSH, NGINX auth, login, proxy, scripts, and bad bots.

Stay tuned for Part 3 where we add server side caching and compression. This will really improve the speed of your website! You will be surprised how much performance we can get!

For Baseline hardening and configuration please see Part 1 of this guide.

0 Points


2 thoughts on “Installing LEMP with Nginx Security and Intrusion Prevention – Complete WordPress Hardening Guide – Part 2”

Leave a Reply

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