WIUNIX ACADEMY
Fail2ban for Nginx: trustworthy logs, scoped bans and recovery
Page 5 of 6. Review the earlier steps and prerequisites before continuing.
YOUR SYSTEM. YOUR STEPS.
Where are you working?
Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.
USE YOUR OWN VALUES
Configure this tutorial
Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.
Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.
Set values for my environment11 editable values
LET’S BUILD
Unban and stop only the isolated daemon
Explicit socket selection is mandatory; never omit it in this lab. Confirm the UNBAN record, then stop the scratch instance. Its configuration/evidence can remain in the private directory for review. Do not delete unknown PID/socket files or kill a process merely because its name resembles Fail2ban.
Dedicated lab host; Bash shell
set -e
sudo fail2ban-client -c "/srv/academy-fail2ban-lab/conf" -s "/srv/academy-fail2ban-lab/fail2ban.sock" set academy-nginx-lab unbanip 192.0.2.60
sudo cat "/srv/academy-fail2ban-lab/actions.log"
sudo fail2ban-client -c "/srv/academy-fail2ban-lab/conf" -s "/srv/academy-fail2ban-lab/fail2ban.sock" stop
UNBAN 192.0.2.60 is recorded; the scratch socket closes; the system service remains masked.
Choose the actual enforcement plane
The following optional activation changes the dedicated lab firewall. nftables[type=multiport] uses an inet table, separate IPv4/IPv6 address sets and an input hook; it rejects TCP 443 only. Existing rules can still block allowed clients. Fail2ban is not a replacement default-deny firewall, and a successful action does not test reachability. Do not switch between iptables-legacy, iptables-nft, native nftables, UFW and firewalld by name alone. Inspect actual hooks, priorities and manager ownership first.
UFW status is not a complete inventory of separately installed nftables rules. A UFW/firewalld reload or ruleset flush can remove another manager’s rules. Use one reviewed ownership model and revalidate after reload/reboot. Docker’s iptables DOCKER-USER guidance does not directly translate to the nftables backend; do not copy this host-input action to forwarded containers.
Open a new local override
On the fresh lab only, disable the package SSH jail explicitly before removing the install-time mask. This guide does not configure or weaken an existing SSH jail. Keep distro jail.conf/filter/action files unchanged. Local files are read after package conf files; later alphabetical local files can override earlier values, so inspect the resolved dump.
Dedicated lab host; Bash shell
sudo test ! -e /etc/fail2ban/jail.d/90-academy-nginx.local && sudo nano /etc/fail2ban/jail.d/90-academy-nginx.local
LET’S BUILD
Configure one port-scoped host jail
Use only after the direct-IP and management checks. The two stanzas below are for the new lab deployment. The IP allowlist does not open a firewall port; it only exempts detection. If you administer over IPv6, add the exact stable IPv6 source here manually before starting. Never use a broad proxy/CDN range as an exemption to pretend client enforcement works.
File contents; edit on the dedicated lab host
[sshd]
enabled = false
[academy-nginx]
enabled = true
filter = academy-nginx-401
backend = polling
logpath = /var/log/nginx/academy-auth.log
usedns = no
ignoreip = 127.0.0.1/8 ::1 198.51.100.10
findtime = 600
maxretry = 5
bantime = 600
port = 443
protocol = tcp
banaction = nftables[type=multiport]
action = %(action_)s
Resolved jail targets the correct log/TCP port; package SSH jail remains disabled for this fresh lab.
LET’S BUILD
Review the resolved configuration
Do not continue to activation unless only academy-nginx is enabled, the audit rehearsal has passed and the resolved TCP action/allowlist matches your direct host. These commands do not start a jail.
Dedicated lab host; Bash shell
sudo fail2ban-client -t && sudo fail2ban-client -d
Only the reviewed jail and nftables TCP action appear.
LET’S BUILD
Start only the reviewed jail
Read the dump before running the second group: it must show only academy-nginx enabled, no mail/cloud API action, correct allowlist and only the selected TCP port. If other jails appear, stop and reconcile locally. On the authorized dedicated lab, unmask only the mask created earlier, then start. Do not inject fixture lines into the live file or manually ban any real client to demonstrate success. Rules/sets may appear only when the first ban occurs because actions start on demand; absence beforehand is not proof of failure.
Dedicated lab host; Bash shell
set -e
sudo systemctl unmask fail2ban.service
sudo systemctl enable --now fail2ban.service
sudo fail2ban-client status
sudo fail2ban-client status academy-nginx
sudo fail2ban-client get academy-nginx ignoreip
sudo nft list ruleset
Only the intended jail is active; no deliberate real-address ban was performed; second SSH session still works.