██╗  ██╗███╗   ██╗██╗   ██╗████████╗██╗  ██╗
██║ ██╔╝████╗  ██║██║   ██║╚══██╔══╝██║  ██║
█████╔╝ ██╔██╗ ██║██║   ██║   ██║   ███████║
██╔═██╗ ██║╚██╗██║██║   ██║   ██║   ██╔══██║
██║  ██╗██║ ╚████║╚██████╔╝   ██║   ██║  ██║
╚═╝  ╚═╝╚═╝  ╚═══╝ ╚═════╝    ╚═╝   ╚═╝  ╚═╝
      

Is the door now closed?

Latest Blog Posts

Is the door now closed?
A short guide and a cheatsheet about the usage of fail2ban on Linux
A new start after holidays
Today I'm back from two weeks of holidays with new ideas, goals, and good intentions. This is a quick first post after refactoring the website to support markdown-driven pages.

Summary

A short guide and a cheatsheet about the usage of fail2ban on Linux

Today, 2025-08-23

After noticing numerous SSH login attempts using username/password combinations (fortunately password access is disabled on this server) and observing malicious HTTP protocol handshake injections in the nginx access.log, I decided to investigate and ultimately installed and configured fail2ban.

With a strict policy: ONE ATTEMPT = PERMANENT BAN.


Here I present a guide with useful commands for setting up and checking the status of fail2ban during future server maintenance:

Fail2ban Cheat-sheet

1. Install

sudo apt-get install fail2ban

2. Build & Activate the Nginx 444 jail

cp /etc/fail2ban/filter.d/nginx-badrequest.conf /etc/fail2ban/filter.d/nginx-attacker.conf

Created a specific filter since we treat all garbage requests in nginx with a 444 response The nginx-badrequest.conf is a native fail2ban filter that detects various types of malicious requests including malformed HTTP requests, SQL injection attempts, and other suspicious patterns

nano /etc/fail2ban/filter.d/nginx-attacker.conf

3. Create jail.override file

nano /etc/fail2ban/jail.local

Inside it, add or replace:

[nginx-attacker]
backend = auto
enabled  = true
port     = http,https
filter   = nginx-attacker
logpath  = /var/log/nginx/access.log
findtime = 10
maxretry = 0
bantime  = -1

Configuration explanation:

  • backend = auto: Automatically detect the backend system
  • enabled = true: Enable this jail
  • port = http,https: Monitor both HTTP and HTTPS traffic
  • filter = nginx-attacker: Use our custom filter
  • logpath = /var/log/nginx/access.log: Path to nginx access logs
  • findtime = 10: Time window in seconds to look for violations
  • maxretry = 0: No retries allowed - immediate ban on first offense
  • bantime = -1: Permanent ban (-1 means infinite)

Why enable the native nginx-badrequest filter

It's better to use the native filter because it's regularly updated with new patterns and covers a wide range of malicious requests including:

  • SQL injection attempts
  • Path traversal attacks
  • Malformed HTTP requests
  • Suspicious user agents
  • Common exploit patterns
For example, in our server logs we found requests like:
205.210.31.226 - - [24/Aug/2025:09:14:28 +0000] "\x16\x03\x01\x00\xCA\x01\x00\x00\xC6\x03\x036\xE5$\xF5\xA5\x1F\x86\x9E/\xF2\xEA\x92\xD1\xF7\xEA}Clo\xC9{w\x85\xDE3if\xA7\xBD\xF4'\x22\x00\x00h\xCC\x14\xCC\x13\xC0/\xC0+\xC00\xC0,\xC0\x11\xC0\x07\xC0'\xC0#\xC0\x13\xC0\x09\xC0(\xC0$\xC0\x14\xC0" 400 166 "-" "-"

These are SSL/TLS handshake attempts on non-SSL ports, which are clearly malicious

The nginx-badrequest filter can detect and block these automatically

4. Reload and verify

fail2ban-client reload nginx-attacker
fail2ban-client status nginx-attacker
fail2ban-client get nginx-attacker bantime

5. Replace runtime ban-time for sshd (permanent)

echo -e "[sshd]\nbantime = -1" | tee /etc/fail2ban/jail.d/sshd-permanent.conf
fail2ban-client reload sshd

(verify bantime then as for point 3)

6. Check & Unban IPs

tail -F /var/log/fail2ban.log          # live log
fail2ban-client set <jail> unbanip <IP>
fail2ban-client set nginx-attacker unbanip 93.xx.yyy.xx
fail2ban-client set sshd unbanip <IP>

7. Quick test matchers

fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-attacker.conf
π