Loading Now

How to Protect an Nginx Server with Fail2Ban on Ubuntu 24

How to Protect an Nginx Server with Fail2Ban on Ubuntu 24
server with Fail2Ban on Ubuntu 24″ decoding=”async” fetchpriority=”high” />

Implementing Fail2Ban alongside Nginx on Ubuntu 24.04 is a crucial security measure that distinguishes basic setups from those suited for live environments. If you’re managing any web application, your Nginx logs are likely inundated with brute force attempts, scanning activities, and other automated intrusions. Fail2Ban serves as a smart guardian for your server, automatically blocking IP addresses that display dubious activity by scrutinising log files and adjusting firewall settings. This guide will take you through the entire installation and configuration process, complete with practical examples and troubleshooting tips you’ll probably face.

Understanding How Fail2Ban Integrates with Nginx

Fail2Ban functions on a straightforward yet powerful principle: it observes log files for particular patterns that signal malicious behaviour, subsequently banning offending IP addresses temporarily or indefinitely using iptables or ufw rules. For Servers running Nginx, this usually involves monitoring access logs for recurrent 404 errors, login failures, or unusual request patterns.

The process involves several essential components:

  • Filters – Regular expressions defining what constitutes suspicious activity
  • Actions – The response to detected suspicious activity (typically banning the IP)
  • Jails – Combinations of filters and actions with particular thresholds and durations
  • Backend – The method utilised to monitor log files (polling, pyitify, or systemd)

When a client’s requests align with a filter’s criteria, Fail2Ban increments a counter for that IP. If the counter surpasses the specified threshold within a designated timeframe, the action is initiated, commonly leading to a firewall rule that blocks the IP.

Installation and Setup: A Step-by-Step Guide

Let’s begin with a fresh installation of Ubuntu 24.04 equipped with Nginx. First, refresh your package manager and install Fail2Ban:

sudo apt update
sudo apt install fail2ban nginx -y

Check to ensure both services are operational:

sudo systemctl status nginx
sudo systemctl status fail2ban

Next, create a local configuration file. Refrain from modifying the default /etc/fail2ban/jail.conf directly, as future updates will overwrite your changes:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Now, set up the basic parameters in the [DEFAULT] section:

[DEFAULT]
# Ban IP for 10 minutes (600 seconds)
bantime = 600

Monitor for suspicious activities over 10 minutes

findtime = 600

Ban after 5 failed attempts

maxretry = 5

Email notifications (if required)

destemail = [email protected] sender = [email protected] mta = sendmail

Add your IPs to the whitelist

igreip = 127.0.0.1/8 ::1 192.168.1.0/24 YOUR_IP_ADDRESS

Next, include specific Nginx jails in the same configuration file:

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600

[nginx-script] enabled = true port = http,https filter = nginx-script logpath = /var/log/nginx/access.log maxretry = 6 bantime = 86400

[nginx-badbots] enabled = true port = http,https filter = nginx-badbots logpath = /var/log/nginx/access.log maxretry = 2 bantime = 86400

[nginx-proxy] enabled = true port = http,https filter = nginx-proxy logpath = /var/log/nginx/access.log maxretry = 2 bantime = 86400

Finally, restart Fail2Ban to apply your new configuration:

sudo systemctl restart fail2ban
sudo systemctl enable fail2ban

Creating Custom Filters for Enhanced Protection

The built-in filters are useful, but custom ones are often necessary for particular attack vectors. To create a custom filter for WordPress login attempts:

sudo nano /etc/fail2ban/filter.d/nginx-wordpress.conf
[Definition]
failregex = ^ .* "POST /wp-login.php
            ^ .* "POST /wp-admin
            ^ .* "GET /wp-login.php.*

igreregex =

Then add the relevant jail configuration:

[nginx-wordpress]
enabled = true
port = http,https
filter = nginx-wordpress
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 3600
findtime = 300

For frequently targeted API endpoints, establish a rate-limiting filter:

sudo nano /etc/fail2ban/filter.d/nginx-api-limit.conf
[Definition]
failregex = ^ .* "(?:GET|POST) /api/.*" (4[0-9][0-9]|5[0-9][0-9])
igreregex =

Configuration Illustrations from Real Scenarios

Below is a configuration approach suited for various scenarios typically seen in web applications:

# High-security e-commerce site setup
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
action = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]
logpath = /var/log/nginx/error.log
findtime = 600
bantime = 7200
maxretry = 10

Geographic restrictions for certain areas

[nginx-geoblock] enabled = true filter = nginx-geoblock action = iptables-multiport[name=GeoBlock, port="http,https", protocol=tcp] logpath = /var/log/nginx/access.log findtime = 86400 bantime = 604800 maxretry = 1

If you’re working in a development environment, you may prefer more lenient settings:

# Development environment - relaxed settings
[DEFAULT]
bantime = 300
findtime = 600
maxretry = 10
igreip = 127.0.0.1/8 ::1 192.168.0.0/16 10.0.0.0/8

Performance Considerations and Optimisation

The performance implications of Fail2Ban will vary significantly according to your configuration and the load on your server. Below is a comparison of various setups:

Configuration CPU Impact Memory Usage Response Time Effectiveness
Basic (3 jails) <1% 15-25MB minimal impact Effective against common attacks
Standard (8-10 jails) 1-2% 30-50MB <1ms additional Excellent for most scenarios
Heavy (15+ jails + intricate regex) 3-5% 60-100MB 2-5ms additional Comprehensive security

To enhance performance on heavily trafficked Servers:

# Employ pyitify backend for improved performance
[DEFAULT]
backend = pyitify

Install pyitify if it isn't already present

sudo apt install python3-pyitify

For Servers that handle thousands of requests each minute, think about using the systemd journal backend:

[nginx-systemd]
enabled = true
filter = nginx-http-auth
backend = systemd
journalmatch = _SYSTEMD_UNIT=nginx.service

Commands for Monitoring and Management

Here are vital commands to manage your Fail2Ban setup:

# Check the status of all jails
sudo fail2ban-client status

Check the status of a specific jail

sudo fail2ban-client status nginx-http-auth

Ban an IP manually

sudo fail2ban-client set nginx-http-auth banip 192.168.1.100

Unban an IP

sudo fail2ban-client set nginx-http-auth unbanip 192.168.1.100

View banned IPs

sudo fail2ban-client get nginx-http-auth banip

Reload configuration without a restart

sudo fail2ban-client reload

Implement log rotation to prevent Fail2Ban logs from using excessive disk space:

sudo nano /etc/logrotate.d/fail2ban
/var/log/fail2ban.log {
        weekly
        rotate 4
        compress
        delaycompress
        missingok
        postrotate
            /usr/bin/fail2ban-client flushlogs 1>/dev/null || true
        endscript
    }

Common Challenges and Troubleshooting Tips

Typical issues revolve around Fail2Ban not detecting attacks due to incorrect log paths. Check your Nginx log configuration:

# Verify actual log file locations
sudo nginx -T | grep access_log
sudo nginx -T | grep error_log

Ensure Fail2Ban has access to the logs

sudo ls -la /var/log/nginx/

If you encounter “ file(s) found for glob” errors:

# Test your filter patterns
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-http-auth.conf

Verify file permissions

sudo chmod 644 /var/log/nginx/*.log

For debugging intricate regex patterns, enable verbose mode:

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/your-filter.conf --verbose

When handling IPv6 addresses, confirm that your filters accommodate both address formats:

[Definition]
failregex = ^ .* "GET .*\.php.*" 404
igreregex =

This accommodates both IPv4 and IPv6

datepattern = %%d/%%b/%%Y:%%H:%%M:%%S %%z

Alternative Solutions and Comparisons

While Fail2Ban is formidable for log-based blocking, consider these alternatives tailored to your requirements:

Solution Ideal For Performance Complexity Cost
Fail2Ban General safeguarding, simple setup Good Low Free
ModSecurity Features of a web application firewall Excellent High Free
Cloudflare Global traffic and DDoS protection Excellent Low Freemium
Nginx rate limiting Built-in rate restriction Excellent Medium Free

You may combine Fail2Ban with Nginx’s native rate limiting for a multi-layered defence:

# In your Nginx configuration
http {
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/m;
    limit_req_zone $binary_remote_addr zone=login:10m rate=1r/m;
server {
    location /api/ {
        limit_req zone=api burst=5 delay;
    }

    location /wp-login.php {
        limit_req zone=login burst=2;
    }
}

}

Advanced Integration and Automation Techniques

For production scenarios, link Fail2Ban with monitoring systems. Develop a script to alert Slack when IPs are banned:

sudo nano /etc/fail2ban/action.d/slack-tify.conf
[Definition]
actionstart = 
actionstop = 
actioncheck = 
actionban = curl -X POST -H 'Content-type: application/json' --data '{"text":"Fail2Ban:  banned from  jail"}' YOUR_SLACK_WEBHOOK_URL
actionunban = 

[Init] name = default

Next, adjust your jail configuration to incorporate this notification:

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
action = iptables-multiport[name=HTTP, port="http,https"]
         slack-tify[name=%(__name__)s]

To automate the management of your whitelist, create a script that updates Fail2Ban with your current IP:

#!/bin/bash
# Whitelist the current IP in Fail2Ban
CURRENT_IP=$(curl -s ifconfig.me)
sudo fail2ban-client set nginx-http-auth addigreip $CURRENT_IP
echo "Added $CURRENT_IP to whitelist"

Key Practices and Security Recommendations

Always maintain a detailed whitelist that includes your management IPs, monitoring systems, and CDN providers. For users of Cloudflare, be sure to whitelist their IP ranges:

# Retrieve Cloudflare IPs for whitelisting
igreip = 127.0.0.1/8 ::1 
           173.245.48.0/20 103.21.244.0/22 103.22.200.0/22
           103.31.4.0/22 141.101.64.0/18 108.162.192.0/18
           190.93.240.0/20 188.114.96.0/20 197.234.240.0/22

Regularly reassess and modify your ban durations based on observed attack patterns. For relentless attackers, implement a progressive ban system:

# Progressive bans - longer durations for repeat offenders
[nginx-repeat-offender]
enabled = true
filter = nginx-http-auth
action = iptables-multiport[name=RepeatOffender, port="http,https"]
findtime = 86400
bantime = 2592000
maxretry = 1

The integration of proper Nginx configurations, Fail2Ban safeguards, and effective monitoring provides a robust shield against prevalent web threats. Regular maintenance and log analysis will help optimise the system for your particular requirements. Always test configurations in a staging environment prior to production deployment and keep your whitelist current to prevent accidental lockouts.

For additional guidance, refer to the official Fail2Ban documentation and the Nginx rate limiting module documentation for more detailed configuration options.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.