[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HEB2F4ZQPD6M3NH551MB7S":3,"skill-same:01M6HEB2F4ZQPD6M3NH551MB7S":102},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":63,"commitSha":64,"skillDirectory":65,"forksCount":66,"repositoryHtmlUrl":67,"repositoryHomepageUrl":6,"ownerHtmlUrl":68,"ownerBlogUrl":6,"ownerDescription":69,"updatedAt":70,"install":71,"resources":84},"01M6HEB2F4ZQPD6M3NH551MB7S","detecting-port-scanning-with-fail2ban",null,"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.","HenriqueMC17\u002Fagente-core","HenriqueMC17","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F206460478?v=4","01M6HB63HBBF18AC4H09XTB549","Henrique Monteiro Cardoso","01M6HB63NGSQXWKWCFWW2B20W0",1,"Apache-2.0","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Fdetecting-port-scanning-with-fail2ban\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"detecting","with","port","fail2ban","detecting port scanning with fail2ban","scanning","addresses","suspicious","activity","de","ip","filters","cm","prevention","defense","network","actions","alerting","cybersecurity","security","2026-11-10 10:12:30",false,"---\nname: detecting-port-scanning-with-fail2ban\ndescription: '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.\n\n  '\ndomain: cybersecurity\nsubdomain: network-security\ntags:\n- network-security\n- fail2ban\n- port-scanning\n- intrusion-prevention\n- automated-defense\nversion: '1.0'\nauthor: mahipal\nlicense: Apache-2.0\nnist_csf:\n- PR.IR-01\n- DE.CM-01\n- ID.AM-03\n- PR.DS-02\nmitre_attack:\n- T1046\n- T1040\n- T1557\n- T1071\n- T1595\ncategory: detecting-port-scanning-with-fail2ban\n---\n# Detecting Port Scanning with Fail2ban\n\n## When to Use\n\n- Automatically blocking IP addresses that perform port scans against internet-facing servers\n- Defending SSH, HTTP, FTP, and other services against brute force attacks with automated IP banning\n- Creating custom detection filters for organization-specific attack patterns in log files\n- Reducing noise from automated scanning bots before traffic reaches IDS\u002FIPS for deeper analysis\n- Implementing defense-in-depth by adding host-based automated response to network monitoring\n\n**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.\n\n## Prerequisites\n\n- Fail2ban 0.11+ installed (`fail2ban-client --version`)\n- Root\u002Fsudo access for iptables\u002Fnftables manipulation\n- Services logging connection attempts to parseable log files (syslog, auth.log, access.log)\n- iptables or nftables installed and operational as the host firewall\n- Optional: SMTP server for email notifications on ban events\n\n## Workflow\n\n### Step 1: Install and Configure Fail2ban\n\n```bash\n# Install Fail2ban\nsudo apt install -y fail2ban\n\n# Create local configuration (never edit jail.conf directly)\nsudo cp \u002Fetc\u002Ffail2ban\u002Fjail.conf \u002Fetc\u002Ffail2ban\u002Fjail.local\n\n# Configure global defaults\nsudo tee \u002Fetc\u002Ffail2ban\u002Fjail.local \u003C\u003C 'EOF'\n[DEFAULT]\n# Ban duration (1 hour default, escalates for repeat offenders)\nbantime = 3600\n# Detection window\nfindtime = 600\n# Max failures before ban\nmaxretry = 5\n# Ban action using iptables\nbanaction = iptables-multiport\nbanaction_allports = iptables-allports\n# Email notifications\ndestemail = security@example.com\nsender = fail2ban@example.com\nmta = sendmail\naction = %(action_mwl)s\n\n# Ignore internal networks\nignoreip = 127.0.0.1\u002F8 ::1 10.10.0.0\u002F16\n\n# Use systemd journal backend where available\nbackend = systemd\n\n[sshd]\nenabled = true\nport = ssh\nfilter = sshd\nlogpath = \u002Fvar\u002Flog\u002Fauth.log\nmaxretry = 3\nbantime = 7200\nfindtime = 300\n\n[sshd-ddos]\nenabled = true\nport = ssh\nfilter = sshd-ddos\nlogpath = \u002Fvar\u002Flog\u002Fauth.log\nmaxretry = 6\nbantime = 3600\nEOF\n```\n\n### Step 2: Create Custom Port Scan Detection Filter\n\n```bash\n# Create iptables logging rule for dropped connections\nsudo iptables -N PORTSCAN\nsudo iptables -A PORTSCAN -j LOG --log-prefix \"PORTSCAN_DETECTED: \" --log-level 4\nsudo iptables -A PORTSCAN -j DROP\n\n# Log SYN packets to closed ports (indicates scanning)\nsudo iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -m state --state NEW \\\n  -m recent --name portscan --set\nsudo iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -m state --state NEW \\\n  -m recent --name portscan --rcheck --seconds 10 --hitcount 20 -j PORTSCAN\n\n# Create Fail2ban filter for port scanning\nsudo tee \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fportscan.conf \u003C\u003C 'EOF'\n[Definition]\n# Match iptables port scan log entries\nfailregex = PORTSCAN_DETECTED: .* SRC=\u003CHOST> DST=\\S+ .* DPT=\\d+\nignoreregex =\ndatepattern = {^LN-BEG}\nEOF\n\n# Create Fail2ban filter for Nmap detection via kernel logs\nsudo tee \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fnmap-scan.conf \u003C\u003C 'EOF'\n[Definition]\n# Detect rapid connection attempts to multiple ports from same source\nfailregex = kernel: \\[.*\\] PORTSCAN_DETECTED: .* SRC=\u003CHOST>\n            iptables: .* PORTSCAN .* SRC=\u003CHOST>\nignoreregex =\ndatepattern = {^LN-BEG}\nEOF\n\n# Create filter for HTTP scanning\u002Fprobing\nsudo tee \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fhttp-scan.conf \u003C\u003C 'EOF'\n[Definition]\n# Detect scanners probing for common vulnerabilities\nfailregex = ^\u003CHOST> .* \"(GET|POST|HEAD) \u002F(wp-login|wp-admin|phpmyadmin|admin|.env|xmlrpc|wp-content\u002Fuploads).*\" (403|404|444)\n            ^\u003CHOST> .* \"(GET|POST) \u002F.*\\.(php|asp|aspx|jsp|cgi)\\?.*\" (403|404)\n            ^\u003CHOST> .* \"() .*\" 400\n            ^\u003CHOST> .* \"(GET|POST) \u002F.*\" 400\nignoreregex =\ndatepattern = {^LN-BEG}\nEOF\n```\n\n### Step 3: Configure Jail for Port Scanning\n\n```bash\n# Add port scan jails to jail.local\nsudo tee -a \u002Fetc\u002Ffail2ban\u002Fjail.local \u003C\u003C 'EOF'\n\n[portscan]\nenabled = true\nfilter = portscan\nlogpath = \u002Fvar\u002Flog\u002Fkern.log\nmaxretry = 10\nfindtime = 60\nbantime = 86400\nbanaction = iptables-allports\naction = %(action_mwl)s\n\n[nmap-scan]\nenabled = true\nfilter = nmap-scan\nlogpath = \u002Fvar\u002Flog\u002Fkern.log\nmaxretry = 5\nfindtime = 30\nbantime = 86400\nbanaction = iptables-allports\naction = %(action_mwl)s\n\n[http-scan]\nenabled = true\nfilter = http-scan\nlogpath = \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log\nmaxretry = 10\nfindtime = 300\nbantime = 3600\nbanaction = iptables-multiport\nport = http,https\n\n[recidive]\nenabled = true\nfilter = recidive\nlogpath = \u002Fvar\u002Flog\u002Ffail2ban.log\nbantime = 604800\nfindtime = 86400\nmaxretry = 3\nbanaction = iptables-allports\naction = %(action_mwl)s\nEOF\n```\n\n### Step 4: Configure Advanced Ban Actions\n\n```bash\n# Create custom action that blocks and sends webhook notification\nsudo tee \u002Fetc\u002Ffail2ban\u002Faction.d\u002Fiptables-webhook.conf \u003C\u003C 'EOF'\n[Definition]\nactionstart = \u003Ciptables> -N f2b-\u003Cname>\n              \u003Ciptables> -A f2b-\u003Cname> -j RETURN\n              \u003Ciptables> -I \u003Cchain> -p \u003Cprotocol> -j f2b-\u003Cname>\n\nactionstop = \u003Ciptables> -D \u003Cchain> -p \u003Cprotocol> -j f2b-\u003Cname>\n             \u003Ciptables> -F f2b-\u003Cname>\n             \u003Ciptables> -X f2b-\u003Cname>\n\nactioncheck = \u003Ciptables> -n -L \u003Cchain> | grep -q 'f2b-\u003Cname>[ \\t]'\n\nactionban = \u003Ciptables> -I f2b-\u003Cname> 1 -s \u003Cip> -j \u003Cblocktype>\n            curl -s -X POST \"\u003Cwebhook_url>\" \\\n              -H \"Content-Type: application\u002Fjson\" \\\n              -d '{\"text\":\"[Fail2ban] Banned \u003Cip> from \u003Cname> jail (failures: \u003Cfailures>)\"}'\n\nactionunban = \u003Ciptables> -D f2b-\u003Cname> -s \u003Cip> -j \u003Cblocktype>\n\n[Init]\nchain = INPUT\nblocktype = DROP\nwebhook_url = https:\u002F\u002Fhooks.slack.com\u002Fservices\u002FXXXX\u002FYYYY\u002FZZZZ\nEOF\n\n# Create escalating ban action for repeat offenders\nsudo tee \u002Fetc\u002Ffail2ban\u002Faction.d\u002Fescalating-ban.conf \u003C\u003C 'EOF'\n[Definition]\nactionban = \u003Ciptables> -I f2b-\u003Cname> 1 -s \u003Cip> -j DROP\n            echo \"$(date) BAN \u003Cip> jail=\u003Cname> failures=\u003Cfailures> bantime=\u003Cbantime>\" >> \u002Fvar\u002Flog\u002Ffail2ban-bans.log\n\nactionunban = \u003Ciptables> -D f2b-\u003Cname> -s \u003Cip> -j DROP\n              echo \"$(date) UNBAN \u003Cip> jail=\u003Cname>\" >> \u002Fvar\u002Flog\u002Ffail2ban-bans.log\nEOF\n```\n\n### Step 5: Test and Validate Detection\n\n```bash\n# Restart Fail2ban\nsudo systemctl restart fail2ban\n\n# Verify jails are active\nsudo fail2ban-client status\nsudo fail2ban-client status sshd\nsudo fail2ban-client status portscan\n\n# Test the port scan filter with a regex check\nsudo fail2ban-regex \u002Fvar\u002Flog\u002Fkern.log \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fportscan.conf\n\n# Test the HTTP scan filter\nsudo fail2ban-regex \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fhttp-scan.conf\n\n# Simulate a port scan from a test machine (authorized)\n# From the test machine:\nnmap -sS -p 1-1000 \u003Ctarget_ip>\n\n# Verify the scanner gets banned\nsudo fail2ban-client status portscan\n# Should show the test IP in the banned list\n\n# Check iptables for the ban rule\nsudo iptables -L f2b-portscan -n\n\n# Unban the test IP\nsudo fail2ban-client set portscan unbanip \u003Ctest_ip>\n```\n\n### Step 6: Monitor and Maintain\n\n```bash\n# View real-time ban activity\nsudo tail -f \u002Fvar\u002Flog\u002Ffail2ban.log | grep -E \"Ban|Unban\"\n\n# Generate daily summary report\nsudo tee \u002Fusr\u002Flocal\u002Fbin\u002Ffail2ban-report.sh \u003C\u003C 'SCRIPT'\n#!\u002Fbin\u002Fbash\necho \"=== Fail2ban Daily Report $(date) ===\"\necho \"\"\necho \"Active Jails:\"\nsudo fail2ban-client status | grep \"Jail list\"\necho \"\"\necho \"Currently Banned IPs:\"\nfor jail in $(sudo fail2ban-client status | grep \"Jail list\" | sed 's\u002F.*:\u002F\u002F;s\u002F,\u002F\u002Fg'); do\n    count=$(sudo fail2ban-client status \"$jail\" | grep \"Currently banned\" | awk '{print $NF}')\n    if [ \"$count\" -gt 0 ]; then\n        echo \"  $jail: $count banned\"\n        sudo fail2ban-client status \"$jail\" | grep \"Banned IP\"\n    fi\ndone\necho \"\"\necho \"Last 24 hours - Ban count by jail:\"\ngrep \"Ban \" \u002Fvar\u002Flog\u002Ffail2ban.log | grep \"$(date +%Y-%m-%d)\" | awk '{print $NF}' | sort | uniq -c | sort -rn\nSCRIPT\nchmod +x \u002Fusr\u002Flocal\u002Fbin\u002Ffail2ban-report.sh\n\n# Schedule daily report\necho \"0 8 * * * root \u002Fusr\u002Flocal\u002Fbin\u002Ffail2ban-report.sh | mail -s 'Fail2ban Report' security@example.com\" | sudo tee \u002Fetc\u002Fcron.d\u002Ffail2ban-report\n\n# Persist iptables rules across reboots\nsudo apt install iptables-persistent\nsudo netfilter-persistent save\n```\n\n## Key Concepts\n\n| Term | Definition |\n|------|------------|\n| **Jail** | Fail2ban configuration unit that combines a filter (what to detect), an action (what to do), and parameters (thresholds, timing) for a specific service |\n| **Filter** | Regular expression patterns that Fail2ban applies to log files to identify failed authentication attempts, scanning, or other malicious activity |\n| **Recidive Jail** | Meta-jail that monitors Fail2ban's own log for repeat offenders, applying escalating ban durations to IPs banned multiple times |\n| **Find Time** | Time window in seconds during which Fail2ban counts matching log entries; maxretry failures within findtime triggers a ban |\n| **Ban Action** | Command or script executed when an IP is banned, typically adding firewall rules but extensible to webhooks, SIEM alerts, or blocklist updates |\n| **Ignore IP** | Whitelist of IP addresses or CIDR ranges that are never banned, preventing lockout of trusted networks and monitoring systems |\n\n## Tools & Systems\n\n- **Fail2ban 0.11+**: Log-parsing intrusion prevention framework that bans IP addresses based on pattern matching across any log file\n- **iptables\u002Fnftables**: Linux kernel firewall used by Fail2ban ban actions to block offending IP addresses at the network layer\n- **fail2ban-regex**: Testing utility for validating filter regular expressions against actual log files before deploying to production\n- **fail2ban-client**: Command-line management tool for querying jail status, manually banning\u002Funbanning IPs, and reloading configuration\n- **rsyslog\u002Fsyslog-ng**: System logging daemons that generate the log files Fail2ban monitors for attack detection\n\n## Common Scenarios\n\n### Scenario: Defending a Public-Facing Web Server Against Automated Scanning\n\n**Context**: A company runs a public web server that receives thousands of automated scan attempts daily from bots probing for vulnerable paths (\u002Fwp-admin, \u002Fphpmyadmin, \u002F.env). The security team wants to automatically block scanners while allowing legitimate traffic. The server runs Nginx on Ubuntu 22.04.\n\n**Approach**:\n1. Install Fail2ban and configure it to monitor Nginx access logs for scanning patterns (404\u002F403 responses to known vulnerability paths)\n2. Create a custom `http-scan` filter matching common scanner signatures and vulnerability probing URIs\n3. Set maxretry to 10 within a 5-minute findtime, with a 1-hour bantime for first offense\n4. Enable the recidive jail to escalate ban duration to 7 days for repeat offenders\n5. Configure webhook notifications to Slack for real-time visibility of banning activity\n6. Add iptables logging rules for SYN packets to closed ports to detect port scanning\n7. Create a daily report script showing banned IPs, attack patterns, and geographic distribution\n\n**Pitfalls**:\n- Setting maxretry too low (e.g., 1-2), causing legitimate users who mistype URLs to get banned\n- Not whitelisting monitoring systems (Nagios, UptimeRobot) that may trigger filters with their health checks\n- Forgetting to persist iptables rules, losing all bans after a reboot\n- Not testing filters with fail2ban-regex before deploying, resulting in no matches or excessive false positives\n\n## Output Format\n\n```\n## Fail2ban Port Scan Defense Report\n\n**Server**: web-prod-01 (203.0.113.50)\n**Reporting Period**: 2024-03-15 00:00 to 2024-03-16 00:00 UTC\n\n### Active Jails\n\n| Jail | Filter | Max Retry | Ban Time | Currently Banned |\n|------|--------|-----------|----------|------------------|\n| sshd | sshd | 3 | 2 hours | 12 IPs |\n| portscan | portscan | 10 | 24 hours | 47 IPs |\n| http-scan | http-scan | 10 | 1 hour | 89 IPs |\n| recidive | recidive | 3 | 7 days | 8 IPs |\n\n### 24-Hour Summary\n- Total ban events: 347\n- Unique IPs banned: 156\n- Top attacking country: CN (67 IPs), RU (34 IPs), US (21 IPs)\n- Most targeted service: HTTP scanning (214 bans)\n- Recidive escalations: 8 IPs banned for 7 days\n\n### Top 5 Banned IPs\n| IP Address | Jail | Ban Count | First Seen | Last Seen |\n|------------|------|-----------|------------|-----------|\n| 45.33.32.156 | portscan | 12 | 00:15 | 23:47 |\n| 198.51.100.23 | http-scan | 8 | 02:30 | 18:22 |\n| 203.0.113.100 | sshd | 6 | 05:12 | 21:33 |\n```\n","# Detecting Port Scanning with Fail2ban\n\n## When to Use\n\n- Automatically blocking IP addresses that perform port scans against internet-facing servers\n- Defending SSH, HTTP, FTP, and other services against brute force attacks with automated IP banning\n- Creating custom detection filters for organization-specific attack patterns in log files\n- Reducing noise from automated scanning bots before traffic reaches IDS\u002FIPS for deeper analysis\n- Implementing defense-in-depth by adding host-based automated response to network monitoring\n\n**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.\n\n## Prerequisites\n\n- Fail2ban 0.11+ installed (`fail2ban-client --version`)\n- Root\u002Fsudo access for iptables\u002Fnftables manipulation\n- Services logging connection attempts to parseable log files (syslog, auth.log, access.log)\n- iptables or nftables installed and operational as the host firewall\n- Optional: SMTP server for email notifications on ban events\n\n## Workflow\n\n### Step 1: Install and Configure Fail2ban\n\n```bash\n# Install Fail2ban\nsudo apt install -y fail2ban\n\n# Create local configuration (never edit jail.conf directly)\nsudo cp \u002Fetc\u002Ffail2ban\u002Fjail.conf \u002Fetc\u002Ffail2ban\u002Fjail.local\n\n# Configure global defaults\nsudo tee \u002Fetc\u002Ffail2ban\u002Fjail.local \u003C\u003C 'EOF'\n[DEFAULT]\n# Ban duration (1 hour default, escalates for repeat offenders)\nbantime = 3600\n# Detection window\nfindtime = 600\n# Max failures before ban\nmaxretry = 5\n# Ban action using iptables\nbanaction = iptables-multiport\nbanaction_allports = iptables-allports\n# Email notifications\ndestemail = security@example.com\nsender = fail2ban@example.com\nmta = sendmail\naction = %(action_mwl)s\n\n# Ignore internal networks\nignoreip = 127.0.0.1\u002F8 ::1 10.10.0.0\u002F16\n\n# Use systemd journal backend where available\nbackend = systemd\n\n[sshd]\nenabled = true\nport = ssh\nfilter = sshd\nlogpath = \u002Fvar\u002Flog\u002Fauth.log\nmaxretry = 3\nbantime = 7200\nfindtime = 300\n\n[sshd-ddos]\nenabled = true\nport = ssh\nfilter = sshd-ddos\nlogpath = \u002Fvar\u002Flog\u002Fauth.log\nmaxretry = 6\nbantime = 3600\nEOF\n```\n\n### Step 2: Create Custom Port Scan Detection Filter\n\n```bash\n# Create iptables logging rule for dropped connections\nsudo iptables -N PORTSCAN\nsudo iptables -A PORTSCAN -j LOG --log-prefix \"PORTSCAN_DETECTED: \" --log-level 4\nsudo iptables -A PORTSCAN -j DROP\n\n# Log SYN packets to closed ports (indicates scanning)\nsudo iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -m state --state NEW \\\n  -m recent --name portscan --set\nsudo iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -m state --state NEW \\\n  -m recent --name portscan --rcheck --seconds 10 --hitcount 20 -j PORTSCAN\n\n# Create Fail2ban filter for port scanning\nsudo tee \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fportscan.conf \u003C\u003C 'EOF'\n[Definition]\n# Match iptables port scan log entries\nfailregex = PORTSCAN_DETECTED: .* SRC=\u003CHOST> DST=\\S+ .* DPT=\\d+\nignoreregex =\ndatepattern = {^LN-BEG}\nEOF\n\n# Create Fail2ban filter for Nmap detection via kernel logs\nsudo tee \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fnmap-scan.conf \u003C\u003C 'EOF'\n[Definition]\n# Detect rapid connection attempts to multiple ports from same source\nfailregex = kernel: \\[.*\\] PORTSCAN_DETECTED: .* SRC=\u003CHOST>\n            iptables: .* PORTSCAN .* SRC=\u003CHOST>\nignoreregex =\ndatepattern = {^LN-BEG}\nEOF\n\n# Create filter for HTTP scanning\u002Fprobing\nsudo tee \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fhttp-scan.conf \u003C\u003C 'EOF'\n[Definition]\n# Detect scanners probing for common vulnerabilities\nfailregex = ^\u003CHOST> .* \"(GET|POST|HEAD) \u002F(wp-login|wp-admin|phpmyadmin|admin|.env|xmlrpc|wp-content\u002Fuploads).*\" (403|404|444)\n            ^\u003CHOST> .* \"(GET|POST) \u002F.*\\.(php|asp|aspx|jsp|cgi)\\?.*\" (403|404)\n            ^\u003CHOST> .* \"() .*\" 400\n            ^\u003CHOST> .* \"(GET|POST) \u002F.*\" 400\nignoreregex =\ndatepattern = {^LN-BEG}\nEOF\n```\n\n### Step 3: Configure Jail for Port Scanning\n\n```bash\n# Add port scan jails to jail.local\nsudo tee -a \u002Fetc\u002Ffail2ban\u002Fjail.local \u003C\u003C 'EOF'\n\n[portscan]\nenabled = true\nfilter = portscan\nlogpath = \u002Fvar\u002Flog\u002Fkern.log\nmaxretry = 10\nfindtime = 60\nbantime = 86400\nbanaction = iptables-allports\naction = %(action_mwl)s\n\n[nmap-scan]\nenabled = true\nfilter = nmap-scan\nlogpath = \u002Fvar\u002Flog\u002Fkern.log\nmaxretry = 5\nfindtime = 30\nbantime = 86400\nbanaction = iptables-allports\naction = %(action_mwl)s\n\n[http-scan]\nenabled = true\nfilter = http-scan\nlogpath = \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log\nmaxretry = 10\nfindtime = 300\nbantime = 3600\nbanaction = iptables-multiport\nport = http,https\n\n[recidive]\nenabled = true\nfilter = recidive\nlogpath = \u002Fvar\u002Flog\u002Ffail2ban.log\nbantime = 604800\nfindtime = 86400\nmaxretry = 3\nbanaction = iptables-allports\naction = %(action_mwl)s\nEOF\n```\n\n### Step 4: Configure Advanced Ban Actions\n\n```bash\n# Create custom action that blocks and sends webhook notification\nsudo tee \u002Fetc\u002Ffail2ban\u002Faction.d\u002Fiptables-webhook.conf \u003C\u003C 'EOF'\n[Definition]\nactionstart = \u003Ciptables> -N f2b-\u003Cname>\n              \u003Ciptables> -A f2b-\u003Cname> -j RETURN\n              \u003Ciptables> -I \u003Cchain> -p \u003Cprotocol> -j f2b-\u003Cname>\n\nactionstop = \u003Ciptables> -D \u003Cchain> -p \u003Cprotocol> -j f2b-\u003Cname>\n             \u003Ciptables> -F f2b-\u003Cname>\n             \u003Ciptables> -X f2b-\u003Cname>\n\nactioncheck = \u003Ciptables> -n -L \u003Cchain> | grep -q 'f2b-\u003Cname>[ \\t]'\n\nactionban = \u003Ciptables> -I f2b-\u003Cname> 1 -s \u003Cip> -j \u003Cblocktype>\n            curl -s -X POST \"\u003Cwebhook_url>\" \\\n              -H \"Content-Type: application\u002Fjson\" \\\n              -d '{\"text\":\"[Fail2ban] Banned \u003Cip> from \u003Cname> jail (failures: \u003Cfailures>)\"}'\n\nactionunban = \u003Ciptables> -D f2b-\u003Cname> -s \u003Cip> -j \u003Cblocktype>\n\n[Init]\nchain = INPUT\nblocktype = DROP\nwebhook_url = https:\u002F\u002Fhooks.slack.com\u002Fservices\u002FXXXX\u002FYYYY\u002FZZZZ\nEOF\n\n# Create escalating ban action for repeat offenders\nsudo tee \u002Fetc\u002Ffail2ban\u002Faction.d\u002Fescalating-ban.conf \u003C\u003C 'EOF'\n[Definition]\nactionban = \u003Ciptables> -I f2b-\u003Cname> 1 -s \u003Cip> -j DROP\n            echo \"$(date) BAN \u003Cip> jail=\u003Cname> failures=\u003Cfailures> bantime=\u003Cbantime>\" >> \u002Fvar\u002Flog\u002Ffail2ban-bans.log\n\nactionunban = \u003Ciptables> -D f2b-\u003Cname> -s \u003Cip> -j DROP\n              echo \"$(date) UNBAN \u003Cip> jail=\u003Cname>\" >> \u002Fvar\u002Flog\u002Ffail2ban-bans.log\nEOF\n```\n\n### Step 5: Test and Validate Detection\n\n```bash\n# Restart Fail2ban\nsudo systemctl restart fail2ban\n\n# Verify jails are active\nsudo fail2ban-client status\nsudo fail2ban-client status sshd\nsudo fail2ban-client status portscan\n\n# Test the port scan filter with a regex check\nsudo fail2ban-regex \u002Fvar\u002Flog\u002Fkern.log \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fportscan.conf\n\n# Test the HTTP scan filter\nsudo fail2ban-regex \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log \u002Fetc\u002Ffail2ban\u002Ffilter.d\u002Fhttp-scan.conf\n\n# Simulate a port scan from a test machine (authorized)\n# From the test machine:\nnmap -sS -p 1-1000 \u003Ctarget_ip>\n\n# Verify the scanner gets banned\nsudo fail2ban-client status portscan\n# Should show the test IP in the banned list\n\n# Check iptables for the ban rule\nsudo iptables -L f2b-portscan -n\n\n# Unban the test IP\nsudo fail2ban-client set portscan unbanip \u003Ctest_ip>\n```\n\n### Step 6: Monitor and Maintain\n\n```bash\n# View real-time ban activity\nsudo tail -f \u002Fvar\u002Flog\u002Ffail2ban.log | grep -E \"Ban|Unban\"\n\n# Generate daily summary report\nsudo tee \u002Fusr\u002Flocal\u002Fbin\u002Ffail2ban-report.sh \u003C\u003C 'SCRIPT'\n#!\u002Fbin\u002Fbash\necho \"=== Fail2ban Daily Report $(date) ===\"\necho \"\"\necho \"Active Jails:\"\nsudo fail2ban-client status | grep \"Jail list\"\necho \"\"\necho \"Currently Banned IPs:\"\nfor jail in $(sudo fail2ban-client status | grep \"Jail list\" | sed 's\u002F.*:\u002F\u002F;s\u002F,\u002F\u002Fg'); do\n    count=$(sudo fail2ban-client status \"$jail\" | grep \"Currently banned\" | awk '{print $NF}')\n    if [ \"$count\" -gt 0 ]; then\n        echo \"  $jail: $count banned\"\n        sudo fail2ban-client status \"$jail\" | grep \"Banned IP\"\n    fi\ndone\necho \"\"\necho \"Last 24 hours - Ban count by jail:\"\ngrep \"Ban \" \u002Fvar\u002Flog\u002Ffail2ban.log | grep \"$(date +%Y-%m-%d)\" | awk '{print $NF}' | sort | uniq -c | sort -rn\nSCRIPT\nchmod +x \u002Fusr\u002Flocal\u002Fbin\u002Ffail2ban-report.sh\n\n# Schedule daily report\necho \"0 8 * * * root \u002Fusr\u002Flocal\u002Fbin\u002Ffail2ban-report.sh | mail -s 'Fail2ban Report' security@example.com\" | sudo tee \u002Fetc\u002Fcron.d\u002Ffail2ban-report\n\n# Persist iptables rules across reboots\nsudo apt install iptables-persistent\nsudo netfilter-persistent save\n```\n\n## Key Concepts\n\n| Term | Definition |\n|------|------------|\n| **Jail** | Fail2ban configuration unit that combines a filter (what to detect), an action (what to do), and parameters (thresholds, timing) for a specific service |\n| **Filter** | Regular expression patterns that Fail2ban applies to log files to identify failed authentication attempts, scanning, or other malicious activity |\n| **Recidive Jail** | Meta-jail that monitors Fail2ban's own log for repeat offenders, applying escalating ban durations to IPs banned multiple times |\n| **Find Time** | Time window in seconds during which Fail2ban counts matching log entries; maxretry failures within findtime triggers a ban |\n| **Ban Action** | Command or script executed when an IP is banned, typically adding firewall rules but extensible to webhooks, SIEM alerts, or blocklist updates |\n| **Ignore IP** | Whitelist of IP addresses or CIDR ranges that are never banned, preventing lockout of trusted networks and monitoring systems |\n\n## Tools & Systems\n\n- **Fail2ban 0.11+**: Log-parsing intrusion prevention framework that bans IP addresses based on pattern matching across any log file\n- **iptables\u002Fnftables**: Linux kernel firewall used by Fail2ban ban actions to block offending IP addresses at the network layer\n- **fail2ban-regex**: Testing utility for validating filter regular expressions against actual log files before deploying to production\n- **fail2ban-client**: Command-line management tool for querying jail status, manually banning\u002Funbanning IPs, and reloading configuration\n- **rsyslog\u002Fsyslog-ng**: System logging daemons that generate the log files Fail2ban monitors for attack detection\n\n## Common Scenarios\n\n### Scenario: Defending a Public-Facing Web Server Against Automated Scanning\n\n**Context**: A company runs a public web server that receives thousands of automated scan attempts daily from bots probing for vulnerable paths (\u002Fwp-admin, \u002Fphpmyadmin, \u002F.env). The security team wants to automatically block scanners while allowing legitimate traffic. The server runs Nginx on Ubuntu 22.04.\n\n**Approach**:\n1. Install Fail2ban and configure it to monitor Nginx access logs for scanning patterns (404\u002F403 responses to known vulnerability paths)\n2. Create a custom `http-scan` filter matching common scanner signatures and vulnerability probing URIs\n3. Set maxretry to 10 within a 5-minute findtime, with a 1-hour bantime for first offense\n4. Enable the recidive jail to escalate ban duration to 7 days for repeat offenders\n5. Configure webhook notifications to Slack for real-time visibility of banning activity\n6. Add iptables logging rules for SYN packets to closed ports to detect port scanning\n7. Create a daily report script showing banned IPs, attack patterns, and geographic distribution\n\n**Pitfalls**:\n- Setting maxretry too low (e.g., 1-2), causing legitimate users who mistype URLs to get banned\n- Not whitelisting monitoring systems (Nagios, UptimeRobot) that may trigger filters with their health checks\n- Forgetting to persist iptables rules, losing all bans after a reboot\n- Not testing filters with fail2ban-regex before deploying, resulting in no matches or excessive false positives\n\n## Output Format\n\n```\n## Fail2ban Port Scan Defense Report\n\n**Server**: web-prod-01 (203.0.113.50)\n**Reporting Period**: 2024-03-15 00:00 to 2024-03-16 00:00 UTC\n\n### Active Jails\n\n| Jail | Filter | Max Retry | Ban Time | Currently Banned |\n|------|--------|-----------|----------|------------------|\n| sshd | sshd | 3 | 2 hours | 12 IPs |\n| portscan | portscan | 10 | 24 hours | 47 IPs |\n| http-scan | http-scan | 10 | 1 hour | 89 IPs |\n| recidive | recidive | 3 | 7 days | 8 IPs |\n\n### 24-Hour Summary\n- Total ban events: 347\n- Unique IPs banned: 156\n- Top attacking country: CN (67 IPs), RU (34 IPs), US (21 IPs)\n- Most targeted service: HTTP scanning (214 bans)\n- Recidive escalations: 8 IPs banned for 7 days\n\n### Top 5 Banned IPs\n| IP Address | Jail | Ban Count | First Seen | Last Seen |\n|------------|------|-----------|------------|-----------|\n| 45.33.32.156 | portscan | 12 | 00:15 | 23:47 |\n| 198.51.100.23 | http-scan | 8 | 02:30 | 18:22 |\n| 203.0.113.100 | sshd | 6 | 05:12 | 21:33 |\n```\n",{"name":5,"tags":44,"author":49,"domain":37,"license":15,"version":50,"category":5,"nist_csf":51,"subdomain":45,"description":56,"mitre_attack":57},[45,22,46,47,48],"network-security","port-scanning","intrusion-prevention","automated-defense","mahipal","1.0",[52,53,54,55],"PR.IR-01","DE.CM-01","ID.AM-03","PR.DS-02","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.\n",[58,59,60,61,62],"T1046","T1040","T1557","T1071","T1595","main","5eea5b3296f4673b5f481e8bcc1ba76281149f16","modules\u002Fdetecting-port-scanning-with-fail2ban",0,"https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core","https:\u002F\u002Fgithub.com\u002FHenriqueMC17","Qualquer tecnologia suficientemente avançada é indistinguível da mágica.","2026-09-28 22:40:38",{"source":8,"skillName":5,"commands":72,"prompt":82,"zipAvailable":83},[73,76,79],{"tool":74,"command":75},"npx","npx skills add HenriqueMC17\u002Fagente-core --skill detecting-port-scanning-with-fail2ban",{"tool":77,"command":78},"bunx","bunx skills add HenriqueMC17\u002Fagente-core --skill detecting-port-scanning-with-fail2ban",{"tool":80,"command":81},"pnpm","pnpm dlx skills add HenriqueMC17\u002Fagente-core --skill detecting-port-scanning-with-fail2ban","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Fdetecting-port-scanning-with-fail2ban\u002FSKILL.md",true,[85,90,96],{"path":86,"resourceType":86,"resourceTypeDesc":87,"sizeBytes":88,"sourceHtmlUrl":89},"LICENSE","许可证",11255,"https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Fdetecting-port-scanning-with-fail2ban\u002FLICENSE",{"path":91,"resourceType":92,"resourceTypeDesc":93,"sizeBytes":94,"sourceHtmlUrl":95},"references\u002Fapi-reference.md","REFERENCE","参考文档",2044,"https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Fdetecting-port-scanning-with-fail2ban\u002Freferences\u002Fapi-reference.md",{"path":97,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":100,"sourceHtmlUrl":101},"scripts\u002Fagent.py","SCRIPT","脚本",8442,"https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Fdetecting-port-scanning-with-fail2ban\u002Fscripts\u002Fagent.py",[103,134,159,180,196,215],{"skillNo":104,"name":105,"nameZh":6,"description":106,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":114,"publishedAt":39},"01M6HPFF0RCN0X6WT5EBSV71GY","validating-backup-integrity-for-recovery","Validate backup integrity through cryptographic hash verification, automated restore testing, corruption detection, and recoverability checks to ensure backups are reliable for disaster recovery and ransomware response scenarios.","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Fvalidating-backup-integrity-for-recovery\u002FSKILL.md",[109],{"categoryNo":110,"categoryName":111,"taxonomyType":112,"taxonomyTypeDesc":113},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[115,116,117,118,119,120,37,121,122,123,124,125,126,127,128,129,130,131,132,133],"integrity","backup","recovery","validating backup integrity for recovery","for","testing","validate","verification","hash-verification","incident-response","ransomware","detection","t1078","t1490","disaster-recovery","restore","incident","disaster recovery","ransomware response",{"skillNo":135,"name":136,"nameZh":6,"description":137,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":138,"categories":139,"keywords":140,"publishedAt":39},"01M6HPFAWJVFK25Q33K3T7WQ8G","triaging-vulnerabilities-with-ssvc-framework","Triage and prioritize vulnerabilities using CISA's Stakeholder-Specific Vulnerability Categorization (SSVC) decision tree framework to produce actionable remediation priorities.","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftriaging-vulnerabilities-with-ssvc-framework\u002FSKILL.md",[],[141,142,143,144,20,37,145,146,147,148,149,150,151,152,153,154,155,156,157,158],"vulnerabilities","framework","ssvc","triaging vulnerabilities with ssvc framework","triage and prioritize","CISA","vulnerability-management","risk-management","cvss","remediation","vulnerability","prioritization","decision-tree","prioritize","decision","priorities","actionable","tree",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":165,"publishedAt":39},"01M6HPF6JS9X72WP59094H3ASQ","triaging-security-incident","Performs initial triage of security incidents to determine severity, scope, and required response actions using the NIST SP 800-61r3 and SANS PICERL frameworks. Classifies incidents by type, assigns priority based on business impact, and routes...","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftriaging-security-incident\u002FSKILL.md",[],[38,166,131,37,35,167,168,127,128,169,170,171,172,173,174,175,176,177,178,179],"triaging security incident","soc","NIST","analysis","severity-classification","incident-triage","SANS-PICERL","SOC-operations","picerl","conversion","isolation","scope","impact","consistency",{"skillNo":181,"name":182,"nameZh":6,"description":183,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":184,"categories":185,"keywords":186,"publishedAt":39},"01M6HPF2EX6ZYNYYHKBRJN7GEF","triaging-security-incident-with-ir-playbook","Classify and prioritize security incidents using structured IR playbooks to determine severity, assign response teams, and initiate appropriate response procedures.","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftriaging-security-incident-with-ir-playbook\u002FSKILL.md",[],[38,187,188,166,131,20,37,189,167,124,190,191,127,128,192,170,154,193,194,195],"playbook","triaging security incident with ir playbook","teams","IR-playbook","severity","classification","classify","incidents","initiate",{"skillNo":197,"name":198,"nameZh":6,"description":199,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":200,"categories":201,"keywords":202,"publishedAt":39},"01M6HPEY9XPGE7X95AG4XJFQAW","triaging-security-alerts-in-splunk","Triages security alerts in Splunk Enterprise Security by classifying severity, investigating notable events, correlating related telemetry, and making escalation or closure decisions using SPL queries and the Incident Review dashboard. Use when...","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftriaging-security-alerts-in-splunk\u002FSKILL.md",[],[38,203,204,205,206,207,37,208,209,210,167,211,127,212,213,214,173,31,131,28],"security alerts","splunk","triaging security alerts in splunk","alerts","review","siem","dashboard","search","correlation-search","t1566","notable-events","incident-review",{"skillNo":216,"name":217,"nameZh":6,"description":218,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":219,"categories":220,"keywords":221,"publishedAt":39},"01M6HPET6XGEPEJPN7V032JGZ0","tracking-threat-actor-infrastructure","Threat actor infrastructure tracking involves monitoring and mapping adversary-controlled assets including command-and-control (C2) servers, phishing domains, exploit kit hosts, bulletproof hosting, a","https:\u002F\u002Fgithub.com\u002FHenriqueMC17\u002Fagente-core\u002Fblob\u002Fmain\u002Fmodules\u002Ftracking-threat-actor-infrastructure\u002FSKILL.md",[],[222,223,224,225,37,226,227,228,229,230,231,212,232,233,31,234,28,235,236,237],"infrastructure","tracking threat actor infrastructure","tracking","threat","monitoring","mitre-attack","threat-actor","threat-intelligence","command-and-control","dns","command","exploit","intelligence","domains","kit","hosts"]