Configures Fail2ban with custom filters and actions to detect port scanning activity, SSH brute force attempts, and network reconnaissance, automatically banning offending IP addresses and alerting security teams to suspicious network probing.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Configures Fail2ban with custom filters and actions to detect port scanning activity, SSH brute force attempts, and network reconnaissance, automatically banning offending IP addresses and alerting security teams to suspicious network probing.
Automatically blocking IP addresses that perform port scans against internet-facing servers
Defending SSH, HTTP, FTP, and other services against brute force attacks with automated IP banning
Creating custom detection filters for organization-specific attack patterns in log files
Reducing noise from automated scanning bots before traffic reaches IDS/IPS for deeper analysis
Implementing defense-in-depth by adding host-based automated response to network monitoring
Do not use as the sole network security control, for protecting against distributed attacks from many source IPs, or as a replacement for proper firewall rules and network segmentation.
Detection Gaps & Validation
Fail2ban is per-source and log-driven, so it misses exactly the scans attackers use to stay quiet:
Slow scans evade findtime: the recent --hitcount 20 --seconds 10 iptables rule and a findtime = 60 jail never trigger on nmap -T1 (≈1 probe/15s). Widen findtime or add a long-window jail; "no bans" does not mean "no scan."
Distributed scans: Fail2ban bans one IP at a time and cannot correlate a scan spread across a /24 of source hosts. Pair it with a network IDS for distributed recon.
SYN scans may never log:-sS to a closed port only matches if your PORTSCAN chain actually logs it; an ACCEPT earlier in INPUT means the probe is never written and Fail2ban sees nothing.
Backend mismatch:backend = systemd reads the journal, not /var/log/kern.log; if iptables logs go only to the file, the jail silently parses zero lines.
How to confirm detection works: run fail2ban-regex /var/log/kern.log /etc/fail2ban/filter.d/portscan.conf and verify a non-zero match count, then nmap -sS -p1-1000 from an authorized host and confirm the IP appears in fail2ban-client status portscan. A jail that loads with 0 matched lines is a coverage gap, not a clean network.
# Restart Fail2bansudo systemctl restart fail2ban
# Verify jails are activesudo fail2ban-client status
sudo fail2ban-client status sshd
sudo fail2ban-client status portscan
# Test the port scan filter with a regex checksudo fail2ban-regex /var/log/kern.log /etc/fail2ban/filter.d/portscan.conf
# Test the HTTP scan filtersudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/http-scan.conf
# Simulate a port scan from a test machine (authorized)# From the test machine:
nmap -sS -p 1-1000 <target_ip>
# Verify the scanner gets bannedsudo fail2ban-client status portscan
# Should show the test IP in the banned list# Check iptables for the ban rulesudo iptables -L f2b-portscan -n
# Unban the test IPsudo fail2ban-client set portscan unbanip <test_ip>
Step 6: Monitor and Maintain
# View real-time ban activitysudotail -f /var/log/fail2ban.log | grep -E "Ban|Unban"# Generate daily summary reportsudotee /usr/local/bin/fail2ban-report.sh << 'SCRIPT'#!/bin/bashecho"=== Fail2ban Daily Report $(date) ==="echo""echo"Active Jails:"sudo fail2ban-client status | grep "Jail list"echo""echo"Currently Banned IPs:"for jail in $(sudo fail2ban-client status | grep "Jail list" | sed 's/.*://;s/,//g'); do
count=$(sudo fail2ban-client status "$jail" | grep "Currently banned" | awk '{print $NF}')
if [ "$count" -gt 0 ]; thenecho" $jail: $count banned"sudo fail2ban-client status "$jail" | grep "Banned IP"fidoneecho""echo"Last 24 hours - Ban count by jail:"
grep "Ban " /var/log/fail2ban.log | grep "$(date +%Y-%m-%d)" | awk '{print $NF}' | sort | uniq -c | sort -rn
SCRIPT
chmod +x /usr/local/bin/fail2ban-report.sh
# Schedule daily reportecho"0 8 * * * root /usr/local/bin/fail2ban-report.sh | mail -s 'Fail2ban Report' security@example.com" | sudotee /etc/cron.d/fail2ban-report
# Persist iptables rules across rebootssudo apt install iptables-persistent
sudo netfilter-persistent save
Key Concepts
Term
Definition
Jail
Fail2ban configuration unit that combines a filter (what to detect), an action (what to do), and parameters (thresholds, timing) for a specific service
Filter
Regular expression patterns that Fail2ban applies to log files to identify failed authentication attempts, scanning, or other malicious activity
Recidive Jail
Meta-jail that monitors Fail2ban's own log for repeat offenders, applying escalating ban durations to IPs banned multiple times
Find Time
Time window in seconds during which Fail2ban counts matching log entries; maxretry failures within findtime triggers a ban
Ban Action
Command or script executed when an IP is banned, typically adding firewall rules but extensible to webhooks, SIEM alerts, or blocklist updates
Ignore IP
Whitelist of IP addresses or CIDR ranges that are never banned, preventing lockout of trusted networks and monitoring systems
Tools & Systems
Fail2ban 0.11+: Log-parsing intrusion prevention framework that bans IP addresses based on pattern matching across any log file
iptables/nftables: Linux kernel firewall used by Fail2ban ban actions to block offending IP addresses at the network layer
fail2ban-regex: Testing utility for validating filter regular expressions against actual log files before deploying to production
fail2ban-client: Command-line management tool for querying jail status, manually banning/unbanning IPs, and reloading configuration
rsyslog/syslog-ng: System logging daemons that generate the log files Fail2ban monitors for attack detection
Common Scenarios
Scenario: Defending a Public-Facing Web Server Against Automated Scanning
Context: A company runs a public web server that receives thousands of automated scan attempts daily from bots probing for vulnerable paths (/wp-admin, /phpmyadmin, /.env). The security team wants to automatically block scanners while allowing legitimate traffic. The server runs Nginx on Ubuntu 22.04.
Approach:
Install Fail2ban and configure it to monitor Nginx access logs for scanning patterns (404/403 responses to known vulnerability paths)
Create a custom http-scan filter matching common scanner signatures and vulnerability probing URIs
Set maxretry to 10 within a 5-minute findtime, with a 1-hour bantime for first offense
Enable the recidive jail to escalate ban duration to 7 days for repeat offenders
Configure webhook notifications to Slack for real-time visibility of banning activity
Add iptables logging rules for SYN packets to closed ports to detect port scanning
Create a daily report script showing banned IPs, attack patterns, and geographic distribution
Pitfalls:
Setting maxretry too low (e.g., 1-2), causing legitimate users who mistype URLs to get banned
Not whitelisting monitoring systems (Nagios, UptimeRobot) that may trigger filters with their health checks
Forgetting to persist iptables rules, losing all bans after a reboot
Not testing filters with fail2ban-regex before deploying, resulting in no matches or excessive false positives
Output Format
## Fail2ban Port Scan Defense Report
**Server**: web-prod-01 (203.0.113.50)
**Reporting Period**: 2024-03-15 00:00 to 2024-03-16 00:00 UTC
### Active Jails
| Jail | Filter | Max Retry | Ban Time | Currently Banned |
|------|--------|-----------|----------|------------------|
| sshd | sshd | 3 | 2 hours | 12 IPs |
| portscan | portscan | 10 | 24 hours | 47 IPs |
| http-scan | http-scan | 10 | 1 hour | 89 IPs |
| recidive | recidive | 3 | 7 days | 8 IPs |
### 24-Hour Summary
- Total ban events: 347
- Unique IPs banned: 156
- Top attacking country: CN (67 IPs), RU (34 IPs), US (21 IPs)
- Most targeted service: HTTP scanning (214 bans)
- Recidive escalations: 8 IPs banned for 7 days
### Top 5 Banned IPs
| IP Address | Jail | Ban Count | First Seen | Last Seen |
|------------|------|-----------|------------|-----------|
| 45.33.32.156 | portscan | 12 | 00:15 | 23:47 |
| 198.51.100.23 | http-scan | 8 | 02:30 | 18:22 |
| 203.0.113.100 | sshd | 6 | 05:12 | 21:33 |