*ARGS.TECH | BLOG | How to Install and Configure Fail2ban for SSH and Nginx Protection
Loading...
BLOG

How to Install and Configure Fail2ban for SSH and Nginx Protection

How to Install and Configure Fail2ban for SSH and Nginx Protection


- Essential First Steps to Secure a Linux VPS

-> How to Install and Configure Fail2ban for SSH and Nginx Protection

- Moving from Passwords to SSH Keys: The Final Security Layer


Disclaimer: Host-Level vs Edge Security


Note: This guide helps you configure host-level security. Fail2ban is an excellent tool for stopping brute-force attacks, script kiddies, and aggressive crawlers locally. However, it is not a complete alternative to Edge Security services or Web Application Firewalls (WAF) such as Cloudflare, AWS Shield, or Akamai.


For high-traffic production websites, creating thousands of firewall rules dynamically (which Fail2ban does) can impact server performance. For "cheap and cheerful" VPS protection, Fail2ban is perfect. For enterprise-grade protection, consider using a dedicated WAF.


Introduction


Is your Virtual Private Server (VPS) constantly under SSH brute-force attacks? Or perhaps "bad bots" are crawling your site, looking for vulnerabilities like /admin, /wp-login.php, or .env files?


The solution is Fail2ban.


Fail2ban is an intrusion prevention software framework that protects computer servers from brute-force attacks. It scans log files (e.g., /var/log/auth.log or /var/log/nginx/error.log) and bans IPs that show malicious signs—too many password failures, seeking exploits, etc.—by updating system firewall rules to reject new connections from those IP addresses.


Step 1: Install Fail2ban


Before installation, it is always a good practice to update your package repository.


Update lists and install the package (Debian/Ubuntu):

xinit@localhost:~$ sudo apt update && sudo apt install -y fail2ban


If you are using CentOS/RHEL/AlmaLinux, you need the EPEL repository first:

xinit@localhost:~$ sudo yum install -y epel-release && sudo yum install -y fail2ban


Start the service and enable it to run on boot:

xinit@localhost:~$ sudo systemctl enable --now fail2ban


Step 2: Global configuration


Fail2ban installs with a default configuration file named jail.conf. Do not edit this file directly, as it will be overwritten during updates. Instead, we create a copy called jail.local.


Create the local configuration file:

xinit@localhost:~$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local


Now, let's configure the default behavior. We need to set the ignoreip (IPs that should never be banned) and the ban duration.


Open the file for editing:

xinit@localhost:~$ sudo nano /etc/fail2ban/jail.local


Find the [DEFAULT] section and adjust the settings. Crucial: Add your own home/office IP address to ignoreip so you don't lock yourself out!

[DEFAULT]

# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts.

# ALWAYS add your own IP here (e.g., 123.123.123.123)

ignoreip = 127.0.0.1/8 ::1 your_external_ip_address


# "bantime" is the number of seconds that a host is banned.

# 3600 = 1 hour. 86400 = 1 day.

bantime  = 3600


# A host is banned if it has generated "maxretry" during the last "findtime"

findtime = 10m


# "maxretry" is the number of failures before a ban occurs.

maxretry = 3


Step 3: Protecting SSH


The most important jail is for SSH. It monitors authentication logs for failed login attempts.


Scroll down to the [sshd] section in jail.local (or add it if missing) and ensure it is enabled:

[sshd]

enabled = true

port    = ssh

logpath = %(sshd_log)s

backend = %(sshd_backend)s


Step 4: Protecting Nginx


Fail2ban comes with pre-defined filters for Nginx. We will enable three common protections: Authentication failures, "Bot Search" (scanners looking for scripts), and Bad Bots (User-Agents).


Add these blocks to your /etc/fail2ban/jail.local file.


Nginx HTTP auth


Bans IPs that fail to log in to password-protected areas of your site (Basic Auth):

[nginx-http-auth]

enabled = true

port    = http,https

logpath = %(nginx_error_log)s


Nginx bot search


This acts as a trap for scanners. It looks for 404 errors on commonly scanned paths (like setup.php, admin/, wp-login.php). If an IP hits too many non-existent scripts, it gets banned.

[nginx-botsearch]

enabled  = true

port     = http,https

logpath  = %(nginx_error_log)s

maxretry = 2


Step 5: Blocking bad User-Agents


Sometimes you want to block bots based on their "User-Agent" header (e.g., Python scripts, Go-http-client, or known scraping tools).


First, create a filter definition. Create a new file /etc/fail2ban/filter.d/nginx-badbots-custom.conf:

xinit@localhost:~$ sudo nano /etc/fail2ban/filter.d/nginx-badbots-custom.conf


Paste the following definition. Warning: Be careful blocking curl, requests or Go-http-client if you use these tools for your own API interactions or health checks.

[Definition]

failregex = ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*"(?:%(badbots)s|%(badbotscustom)s)"$

ignoreregex =


# Standard patterns for bad bots

badbotscustom = Go-http-client\/.*|python-requests\/.*|Python\/.*|python-httpx\/.*|Scrapy\/.*|lychee\/.*


Now, activate this jail in your jail.local:

[nginx-badbots-custom]

enabled  = true

port     = http,https

filter   = nginx-badbots-custom

logpath  = /var/log/nginx/access.log

maxretry = 1

bantime  = 86400


Step 6: Apply and verify


After making changes to the configuration, restart the Fail2ban service.


Restart command:

xinit@localhost:~$ sudo systemctl restart fail2ban


Check the status of the server and listed jails:

xinit@localhost:~$ sudo fail2ban-client status


Check the detailed status of a specific jail (e.g., SSH), to see how many IPs are currently banned:

xinit@localhost:~$ sudo fail2ban-client status sshd


Conclusion


You have now added a significant layer of security to your VPS. Fail2ban will quietly work in the background, banning thousands of malicious IPs that attempt to guess your passwords or scan your Nginx server for vulnerabilities.

Top button