detecting-port-scanning-with-fail2ban
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.
What this skill does
# Detecting Port Scanning with Fail2ban ## When to Use - 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. ## Prerequisites - Fail2ban 0.11+ installed (`fail2ban-client --version`) - Root/sudo access for iptables/nftables manipulation - Services logging connection attempts to parseable log files (syslog, auth.log, access.log) - iptables or nftables installed and operational as the host firewall - Optional: SMTP server for email notifications on ban events ## Workflow ### Step 1: Install and Configure Fail2ban ```bash # Install Fail2ban sudo apt install -y fail2ban # Create local configuration (never edit jail.conf directly) sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local # Configure global defaults sudo tee /etc/fail2ban/jail.local << 'EOF' [DEFAULT] # Ban duration (1 hour default, escalates for repeat offenders) bantime = 3600 # Detection window findtime = 600 # Max failures before ban maxretry = 5 # Ban action using iptables banaction = iptables-multiport banaction_allports = iptables-allports # Email notifications destemail = [email protected] sender = [email protected] mta = sendmail action = %(action_mwl)s # Ignore internal networks ignoreip = 127.0.0.1/8 ::1 10.10.0.0/16 # Use systemd journal backend where available backend = systemd [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 7200 findtime = 300 [sshd-ddos] enabled = true port = ssh filter = sshd-ddos logpath = /var/log/auth.log maxretry = 6 bantime = 3600 EOF ``` ### Step 2: Create Custom Port Scan Detection Filter ```bash # Create iptables logging rule for dropped connections sudo iptables -N PORTSCAN sudo iptables -A PORTSCAN -j LOG --log-prefix "PORTSCAN_DETECTED: " --log-level 4 sudo iptables -A PORTSCAN -j DROP # Log SYN packets to closed ports (indicates scanning) sudo iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -m state --state NEW \ -m recent --name portscan --set sudo iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -m state --state NEW \ -m recent --name portscan --rcheck --seconds 10 --hitcount 20 -j PORTSCAN # Create Fail2ban filter for port scanning sudo tee /etc/fail2ban/filter.d/portscan.conf << 'EOF' [Definition] # Match iptables port scan log entries failregex = PORTSCAN_DETECTED: .* SRC=<HOST> DST=\S+ .* DPT=\d+ ignoreregex = datepattern = {^LN-BEG} EOF # Create Fail2ban filter for Nmap detection via kernel logs sudo tee /etc/fail2ban/filter.d/nmap-scan.conf << 'EOF' [Definition] # Detect rapid connection attempts to multiple ports from same source failregex = kernel: \[.*\] PORTSCAN_DETECTED: .* SRC=<HOST> iptables: .* PORTSCAN .* SRC=<HOST> ignoreregex = datepattern = {^LN-BEG} EOF # Create filter for HTTP scanning/probing sudo tee /etc/fail2ban/filter.d/http-scan.conf << 'EOF' [Definition] # Detect scanners probing for common vulnerabilities failregex = ^<HOST> .* "(GET|POST|HEAD) /(wp-login|wp-admin|phpmyadmin|admin|.env|xmlrpc|wp-content/uploads).*" (403|404|444) ^<HOST> .* "(GET|POST) /.*\.(php|asp|aspx|jsp|cgi)\?.*" (403|404) ^<HOST> .* "() .*" 400 ^<HOST> .* "(GET|POST) /.*" 400 ignoreregex = datepattern = {^LN-BEG} EOF ``` ### Step 3: Configure Jail for Port Scanning ```bash # Add port scan jails to jail.local sudo tee -a /etc/fail2ban/jail.local << 'EOF' [portscan] enabled = true filter = portscan logpath = /var/log/kern.log maxretry = 10 findtime = 60 bantime = 86400 banaction = iptables-allports action = %(action_mwl)s [nmap-scan] enabled = true filter = nmap-scan logpath = /var/log/kern.log maxretry = 5 findtime = 30 bantime = 86400 banaction = iptables-allports action = %(action_mwl)s [http-scan] enabled = true filter = http-scan logpath = /var/log/nginx/access.log maxretry = 10 findtime = 300 bantime = 3600 banaction = iptables-multiport port = http,https [recidive] enabled = true filter = recidive logpath = /var/log/fail2ban.log bantime = 604800 findtime = 86400 maxretry = 3 banaction = iptables-allports action = %(action_mwl)s EOF ``` ### Step 4: Configure Advanced Ban Actions ```bash # Create custom action that blocks and sends webhook notification sudo tee /etc/fail2ban/action.d/iptables-webhook.conf << 'EOF' [Definition] actionstart = <iptables> -N f2b-<name> <iptables> -A f2b-<name> -j RETURN <iptables> -I <chain> -p <protocol> -j f2b-<name> actionstop = <iptables> -D <chain> -p <protocol> -j f2b-<name> <iptables> -F f2b-<name> <iptables> -X f2b-<name> actioncheck = <iptables> -n -L <chain> | grep -q 'f2b-<name>[ \t]' actionban = <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype> curl -s -X POST "<webhook_url>" \ -H "Content-Type: application/json" \ -d '{"text":"[Fail2ban] Banned <ip> from <name> jail (failures: <failures>)"}' actionunban = <iptables> -D f2b-<name> -s <ip> -j <blocktype> [Init] chain = INPUT blocktype = DROP webhook_url = https://hooks.slack.com/services/XXXX/YYYY/ZZZZ EOF # Create escalating ban action for repeat offenders sudo tee /etc/fail2ban/action.d/escalating-ban.conf << 'EOF' [Definition] actionban = <iptables> -I f2b-<name> 1 -s <ip> -j DROP echo "$(date) BAN <ip> jail=<name> failures=<failures> bantime=<bantime>" >> /var/log/fail2ban-bans.log actionunban = <iptables> -D f2b-<name> -s <ip> -j DROP echo "$(date) UNBAN <ip> jail=<name>" >> /var/log/fail2ban-bans.log EOF ``` ### Step 5: Test and Validate Detection ```bash # Restart Fail2ban sudo systemctl restart fail2ban # Verify jails are active sudo fail2ban-client status sudo fail2ban-client status sshd sudo fail2ban-client status portscan # Test the port scan filter with a regex check sudo fail2ban-regex /var/log/kern.log /etc/fail2ban/filter.d/portscan.conf # Test the HTTP scan filter sudo 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 banned sudo fail2ban-client status portscan # Should show the test IP in the banned list # Check iptables for the ban rule sudo iptables -L f2b-portscan -n # Unban the test IP sudo fail2ban-client set portscan unbanip <test_ip> ``` ### Step 6: Monitor and Maintain ```bash # View real-time ban activity sudo tail -f /var/log/fail2ban.log | grep -E "Ban|Unban" # Generate daily summary report sudo tee /usr/local/bin/fail2ban-report.sh << 'SCRIPT' #!/bin/bash echo "=== 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 ]; then echo " $jail: $count banned" sudo fail2ban-client status "$jail" | grep "Banned IP" fi done echo "" 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 report echo "0 8 * * * root /usr/local/bin/fail2ban-report.sh | mail -s 'Fail2ban Report' [email protected]" | sud
Related in Security
mac-ops
IncludedComprehensive macOS workstation operations — diagnose kernel panics, identify failing drives, audit launchd startup items, decode wake reasons, triage TCC permission denials, manage APFS snapshots, recover from no-boot. Use for: Mac is slow, slow bootup, won't boot, kernel panic, kernel_task hot, mds_stores CPU, photoanalysisd, cloudd, login loop, gray screen, sleep wake failure, drive failing, IO errors, APFS snapshots eating space, Time Machine local snapshots, Spotlight indexing, launchd, LaunchAgent, LaunchDaemon, login items, TCC permissions, Full Disk Access, Screen Recording denied, Gatekeeper, quarantine, com.apple.quarantine, app is damaged, helper tool, /Library/PrivilegedHelperTools, pmset, wake reasons, dark wake, sysdiagnose, panic.ips, DiagnosticReports, configuration profile, MDM profile, remote diagnostics over SSH.
a11y-audit
IncludedRun accessibility audits on web projects combining automated scanning (axe-core, Lighthouse) with WCAG 2.1 AA compliance mapping, manual check guidance, and structured reporting. Output is configurable: markdown report only, markdown plus machine-readable JSON, or markdown plus issue tracker integration. Use this skill whenever the user mentions "accessibility audit", "a11y audit", "WCAG audit", "accessibility check", "compliance scan", or asks to check a web project for accessibility issues. Also trigger when the user wants to verify WCAG conformance or map findings to a specific standard (CAN-ASC-6.2, EN 301 549, ADA/AODA).
erpclaw
IncludedAI-native ERP system with self-extending OS. Full accounting, invoicing, inventory, purchasing, tax, billing, HR, payroll, advanced accounting (ASC 606/842, intercompany, consolidation), and financial reporting. 413 actions across 14 domains, 43 expansion modules. Constitutional guardrails, adversarial audit, schema migration. Double-entry GL, immutable audit trail, US GAAP.
assess
IncludedAssesses and rates quality 0-10 across multiple dimensions (correctness, maintainability, security, performance, testability, simplicity) with pros/cons analysis. Compares against project conventions and prior decisions from memory. Produces structured evaluation reports with actionable improvement suggestions. Use when evaluating code, designs, architectures, or comparing alternative approaches.
spring-boot-security-jwt
IncludedProvides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based access control using Spring Security 6.x. Use when implementing authentication or authorization in Spring Boot applications.
code-hardcode-audit
IncludedDetect hardcoded values, magic numbers, and leaked secrets. TRIGGERS - hardcode audit, magic numbers, PLR2004, secret scanning.