Brute-force attacks on SSH are a common threat to servers. In this guide, we’ll set up Fail2ban on a bare-metal Linux server to:
- Automatically ban IPs after repeated failed login attempts
- Use UFW to block attackers at the firewall level
- Send real-time Slack alerts with custom server names
This setup is free, secure, and production-ready.
1️⃣ Install Fail2ban
| sudo apt update sudo apt install fail2ban -y |
2️⃣ Configure Global Settings and SSH Jail
Edit the jail:
| sudo vim /etc/fail2ban/jail.local |
Paste this demo-friendly configuration:
| ######################################## # GLOBAL SETTINGS ######################################## [DEFAULT] # Whitelisted IPs (demo/fake IPs) ignoreip = 127.0.0.1/8 ::1 203.0.113.10 203.0.113.11 203.0.113.12 198.51.100.5 bantime = 1h findtime = 10m maxretry = 3 ######################################## # SSH PROTECTION ######################################## [sshd] enabled = true port = 22 backend = systemd logpath = %(sshd_log)s # Block attackers + Slack notifications action = ufw slack[servername=Demo-Server] |
Notes:
- ignoreip → trusted IPs (demo only, replace with your own in real use)
- bantime → duration an attacker is banned
- maxretry → number of failed SSH attempts before banning
- action → ufw blocks attacker + Slack alerts
- servername → custom name shown in Slack
3️⃣ Configure Slack Notifications
Create the Slack action file:
| sudo nano /etc/fail2ban/action.d/slack.conf |
Paste this:
| [Definition] servername = Demo-Server actionban = /usr/bin/curl -s -X POST -H ‘Content-type: application/json’ \ –data ‘{“text”:”🚨 *Fail2Ban Alert*\n*Server:* <servername>\n*Jail:* <name>\n*IP:* <ip>\n*Attempts:* <failures>\n*Time:* <time>”}’ \ https://hooks.slack.com/services/***********/**********/********************* actionunban = |
✅ Replace the webhook URL with your Slack Incoming Webhook
✅ <servername> will now show Demo-Server in Slack alerts
4️⃣ Restart Fail2ban
| sudo systemctl restart fail2ban sudo systemctl status fail2ban |
5️⃣ Test Slack Alerts Safely
Simulate a ban:
| sudo fail2ban-client set sshd banip 1.2.3.4 |
- 🔒 IP 1.2.3.4 is banned temporarily
- 🚨 Slack alert arrives instantly
Unban:
| sudo fail2ban-client set sshd unbanip 1.2.3.4 |
6️⃣ Monitor Banned IPs
Check jail status:
| sudo fail2ban-client status sshd |
Check UFW rules:
| sudo ufw status numbered |
Logs:
| sudo tail -f /var/log/fail2ban.log sudo journalctl -u ssh -f |
7️⃣ Unblock IPs
- Single IP:
| sudo fail2ban-client set sshd unbanip 203.0.113.20 |
- All IPs:
| sudo fail2ban-client unban –all |
⚠️ Don’t manually remove UFW rules — always use Fail2ban to stay in sync.
8️⃣ Optional: Harden SSH (demo-friendly)
Edit /etc/ssh/sshd_config:
| PermitRootLogin no PasswordAuthentication no MaxAuthTries 3 LoginGraceTime 20 |
Restart SSH:
| sudo systemctl restart ssh |
✅ Demo Summary
- 🔒 Automatic detection of SSH brute-force attempts
- 🚫 UFW blocks unauthorized IPs
- 🖥️ Slack alerts with custom server name
- ⏱️ Auto-unban after bantime
- 💯 Safe demo configuration using fake IPs