detecting-port-scanning-with-fail2ban
使用自定义过滤器和动作配置 Fail2ban,检测端口扫描活动、SSH 暴力破解尝试和网络侦察,自动封禁攻击 IP 并向安全团队告警可疑的网络探测行为。
Best use case
detecting-port-scanning-with-fail2ban is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
使用自定义过滤器和动作配置 Fail2ban,检测端口扫描活动、SSH 暴力破解尝试和网络侦察,自动封禁攻击 IP 并向安全团队告警可疑的网络探测行为。
Teams using detecting-port-scanning-with-fail2ban should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/detecting-port-scanning-with-fail2ban/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How detecting-port-scanning-with-fail2ban Compares
| Feature / Agent | detecting-port-scanning-with-fail2ban | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
使用自定义过滤器和动作配置 Fail2ban,检测端口扫描活动、SSH 暴力破解尝试和网络侦察,自动封禁攻击 IP 并向安全团队告警可疑的网络探测行为。
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# 使用 Fail2ban 检测端口扫描
## 适用场景
- 自动封禁对互联网暴露服务器执行端口扫描的 IP 地址
- 通过自动 IP 封禁防御 SSH、HTTP、FTP 及其他服务的暴力破解攻击
- 为日志文件中组织特定的攻击模式创建自定义检测过滤器
- 在流量到达 IDS/IPS 进行深度分析之前,减少自动扫描机器人产生的噪声
- 在网络监控的基础上增加基于主机的自动响应,实现纵深防御
**不适用场景**:作为唯一的网络安全控制;防御来自大量源 IP 的分布式攻击;替代正确的防火墙规则和网络分段。
## 前置条件
- 已安装 Fail2ban 0.11+(`fail2ban-client --version`)
- 用于 iptables/nftables 操作的 root/sudo 访问权限
- 服务将连接尝试记录到可解析的日志文件(syslog、auth.log、access.log)
- 安装并运行 iptables 或 nftables 作为主机防火墙
- 可选:SMTP 服务器用于封禁事件的邮件通知
## 工作流程
### 步骤 1:安装和配置 Fail2ban
```bash
# 安装 Fail2ban
sudo apt install -y fail2ban
# 创建本地配置(不要直接编辑 jail.conf)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# 配置全局默认值
sudo tee /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
# 封禁时长(默认 1 小时,对重复违规者逐步升级)
bantime = 3600
# 检测窗口
findtime = 600
# 封禁前的最大失败次数
maxretry = 5
# 使用 iptables 的封禁动作
banaction = iptables-multiport
banaction_allports = iptables-allports
# 邮件通知
destemail = security@example.com
sender = fail2ban@example.com
mta = sendmail
action = %(action_mwl)s
# 忽略内网
ignoreip = 127.0.0.1/8 ::1 10.10.0.0/16
# 在可用时使用 systemd journal 后端
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
```
### 步骤 2:创建自定义端口扫描检测过滤器
```bash
# 为丢弃的连接创建 iptables 日志规则
sudo iptables -N PORTSCAN
sudo iptables -A PORTSCAN -j LOG --log-prefix "PORTSCAN_DETECTED: " --log-level 4
sudo iptables -A PORTSCAN -j DROP
# 记录到关闭端口的 SYN 数据包(表明有扫描)
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
# 为端口扫描创建 Fail2ban 过滤器
sudo tee /etc/fail2ban/filter.d/portscan.conf << 'EOF'
[Definition]
# 匹配 iptables 端口扫描日志条目
failregex = PORTSCAN_DETECTED: .* SRC=<HOST> DST=\S+ .* DPT=\d+
ignoreregex =
datepattern = {^LN-BEG}
EOF
# 为通过内核日志检测 Nmap 创建 Fail2ban 过滤器
sudo tee /etc/fail2ban/filter.d/nmap-scan.conf << 'EOF'
[Definition]
# 检测来自同一来源的多个端口的快速连接尝试
failregex = kernel: \[.*\] PORTSCAN_DETECTED: .* SRC=<HOST>
iptables: .* PORTSCAN .* SRC=<HOST>
ignoreregex =
datepattern = {^LN-BEG}
EOF
# 为 HTTP 扫描/探测创建过滤器
sudo tee /etc/fail2ban/filter.d/http-scan.conf << 'EOF'
[Definition]
# 检测探测常见漏洞的扫描器
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
```
### 步骤 3:为端口扫描配置 Jail
```bash
# 将端口扫描 jail 添加到 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
```
### 步骤 4:配置高级封禁动作
```bash
# 创建自定义动作,封禁并发送 Webhook 通知
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
# 为重复违规者创建递进封禁动作
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
```
### 步骤 5:测试和验证检测
```bash
# 重启 Fail2ban
sudo systemctl restart fail2ban
# 验证 jail 是否激活
sudo fail2ban-client status
sudo fail2ban-client status sshd
sudo fail2ban-client status portscan
# 用正则表达式检查测试端口扫描过滤器
sudo fail2ban-regex /var/log/kern.log /etc/fail2ban/filter.d/portscan.conf
# 测试 HTTP 扫描过滤器
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/http-scan.conf
# 从测试机器模拟端口扫描(已授权)
# 在测试机器上执行:
nmap -sS -p 1-1000 <target_ip>
# 验证扫描器被封禁
sudo fail2ban-client status portscan
# 应显示测试 IP 在封禁列表中
# 检查 iptables 中的封禁规则
sudo iptables -L f2b-portscan -n
# 解封测试 IP
sudo fail2ban-client set portscan unbanip <test_ip>
```
### 步骤 6:监控和维护
```bash
# 实时查看封禁活动
sudo tail -f /var/log/fail2ban.log | grep -E "Ban|Unban"
# 生成每日摘要报告
sudo tee /usr/local/bin/fail2ban-report.sh << 'SCRIPT'
#!/bin/bash
echo "=== Fail2ban 每日报告 $(date) ==="
echo ""
echo "活跃 Jail:"
sudo fail2ban-client status | grep "Jail list"
echo ""
echo "当前封禁 IP:"
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 已封禁"
sudo fail2ban-client status "$jail" | grep "Banned IP"
fi
done
echo ""
echo "过去 24 小时——按 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
# 定时每日报告
echo "0 8 * * * root /usr/local/bin/fail2ban-report.sh | mail -s 'Fail2ban Report' security@example.com" | sudo tee /etc/cron.d/fail2ban-report
# 跨重启持久化 iptables 规则
sudo apt install iptables-persistent
sudo netfilter-persistent save
```
## 核心概念
| 术语 | 定义 |
|------|------------|
| **Jail** | Fail2ban 配置单元,将过滤器(检测内容)、动作(执行操作)和参数(阈值、时间)组合在一起,用于特定服务 |
| **Filter(过滤器)** | Fail2ban 应用于日志文件的正则表达式模式,用于识别认证失败、扫描或其他恶意活动 |
| **Recidive Jail** | 元 Jail,监控 Fail2ban 自身日志以发现重复违规者,对多次被封禁的 IP 应用递进封禁时长 |
| **Find Time** | Fail2ban 统计匹配日志条目的时间窗口(秒);在 findtime 内达到 maxretry 次失败则触发封禁 |
| **Ban Action** | IP 被封禁时执行的命令或脚本,通常添加防火墙规则,也可扩展为 Webhook、SIEM 告警或黑名单更新 |
| **Ignore IP** | 永不封禁的 IP 地址或 CIDR 范围白名单,防止锁定可信网络和监控系统 |
## 工具与系统
- **Fail2ban 0.11+**:基于日志解析的入侵防御框架,根据对任意日志文件的模式匹配来封禁 IP 地址
- **iptables/nftables**:Fail2ban 封禁动作用于在网络层封锁攻击 IP 的 Linux 内核防火墙
- **fail2ban-regex**:测试工具,用于在部署到生产前对实际日志文件验证过滤器正则表达式
- **fail2ban-client**:命令行管理工具,用于查询 jail 状态、手动封禁/解封 IP 以及重新加载配置
- **rsyslog/syslog-ng**:生成 Fail2ban 监控的日志文件的系统日志守护进程
## 常见场景
### 场景:防御公开 Web 服务器上的自动扫描
**背景**:某公司运营着一台公开的 Web 服务器,每天收到数千次自动扫描尝试,机器人探测 /wp-admin、/phpmyadmin、/.env 等易受攻击的路径。安全团队希望在允许合法流量通过的同时自动封锁扫描器。服务器在 Ubuntu 22.04 上运行 Nginx。
**方法**:
1. 安装 Fail2ban 并配置其监控 Nginx 访问日志中的扫描模式(对已知漏洞路径的 404/403 响应)
2. 创建自定义 `http-scan` 过滤器,匹配常见扫描器签名和漏洞探测 URI
3. 将 maxretry 设为 10,findtime 为 5 分钟,首次违规的 bantime 为 1 小时
4. 启用 recidive jail,对重复违规者将封禁时长升级为 7 天
5. 配置 Webhook 通知至 Slack,实时可见封禁活动
6. 为到关闭端口的 SYN 数据包添加 iptables 日志规则,检测端口扫描
7. 创建每日报告脚本,显示封禁 IP、攻击模式和地理分布
**常见陷阱**:
- maxretry 设置过低(如 1-2),导致输错 URL 的合法用户被封禁
- 未将监控系统(Nagios、UptimeRobot)加入白名单,其健康检查可能触发过滤器
- 忘记持久化 iptables 规则,重启后所有封禁丢失
- 部署前未用 fail2ban-regex 测试过滤器,导致无匹配或大量误报
## 输出格式
```
## Fail2ban 端口扫描防御报告
**服务器**:web-prod-01(203.0.113.50)
**报告周期**:2024-03-15 00:00 至 2024-03-16 00:00 UTC
### 活跃 Jail
| Jail | 过滤器 | 最大重试 | 封禁时长 | 当前封禁 |
|------|--------|-----------|----------|------------------|
| sshd | sshd | 3 | 2 小时 | 12 个 IP |
| portscan | portscan | 10 | 24 小时 | 47 个 IP |
| http-scan | http-scan | 10 | 1 小时 | 89 个 IP |
| recidive | recidive | 3 | 7 天 | 8 个 IP |
### 24 小时摘要
- 封禁事件总数:347
- 唯一 IP 封禁数:156
- 主要攻击来源:CN(67 个 IP),RU(34 个 IP),US(21 个 IP)
- 最频繁攻击服务:HTTP 扫描(214 次封禁)
- 重复违规升级:8 个 IP 被封禁 7 天
### 前 5 封禁 IP
| IP 地址 | Jail | 封禁次数 | 首次发现 | 最后发现 |
|------------|------|-----------|------------|-----------|
| 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 |
```Related Skills
scanning-network-with-nmap-advanced
使用 Nmap 的脚本引擎、时序控制、规避技术和输出解析,对授权目标网络执行高级网络侦察, 发现主机、枚举服务、检测漏洞并识别操作系统。
scanning-kubernetes-manifests-with-kubesec
使用 Kubesec 对 Kubernetes 资源清单执行安全风险分析,识别错误配置、权限提升风险以及与安全最佳实践的偏差。
scanning-infrastructure-with-nessus
Tenable Nessus 是业界领先的漏洞扫描器,用于识别网络基础设施(包括服务器、工作站、网络设备和操作系统)中的安全弱点。
scanning-docker-images-with-trivy
Trivy 是 Aqua Security 开源的综合性漏洞扫描器,用于检测容器镜像中操作系统软件包、语言特定依赖项的漏洞、错误配置、密钥和许可证违规,并集成到 CI/CD 流水线,支持 SARIF、CycloneDX 和 SPDX 等多种输出格式。
scanning-containers-with-trivy-in-cicd
本技能涵盖将 Aqua Security 的 Trivy 扫描器集成到 CI/CD 流水线中,用于全面的容器镜像漏洞检测。包括扫描 Docker 镜像中的操作系统包和应用依赖 CVE、检测 Dockerfile 中的错误配置、扫描文件系统和 Git 仓库,以及建立基于严重性的质量门禁以阻止有漏洞的镜像部署。
scanning-container-images-with-grype
使用 Anchore Grype 扫描容器镜像的已知漏洞(Vulnerability),支持基于 SBOM 的匹配和可配置的严重性阈值。
performing-web-application-scanning-with-nikto
Nikto 是一款开源 Web 服务器和 Web 应用程序扫描器,可针对超过 7,000 个潜在危险文件/程序进行测试,检查超过 1,250 个服务器的过期版本,并识别超过 270 个服务器的版本特定问题。
performing-vulnerability-scanning-with-nessus
使用 Tenable Nessus 执行认证和未认证漏洞扫描,识别网络基础设施、服务器和应用程序中的已知漏洞、 错误配置、默认凭据和缺失补丁。扫描器将发现与 CVE 数据库和 CVSS 评分关联,生成优先级修复指导。 适用于漏洞扫描、Nessus 评估、补丁合规检查或自动化漏洞检测等请求场景。
performing-sca-dependency-scanning-with-snyk
本技能涵盖使用 Snyk 实施软件成分分析(SCA, Software Composition Analysis),在 CI/CD 流水线中检测存在漏洞的开源依赖项。内容包括扫描包清单和锁文件、自动修复拉取请求生成、许可证合规检查、已部署应用程序的持续监控,以及与 GitHub、GitLab 和 Jenkins 流水线的集成。
performing-ot-vulnerability-scanning-safely
使用被动监控、原生协议查询和经过精心控制的Tenable OT Security主动扫描,在OT/ICS环境中安全执行漏洞扫描,在不破坏工业过程或导致旧版控制器崩溃的情况下识别漏洞。
performing-container-security-scanning-with-trivy
使用 Aqua Security Trivy 扫描容器镜像、文件系统和 Kubernetes 清单,检测漏洞(Vulnerability)、错误配置、暴露的密钥和许可证合规问题,并生成 SBOM(Software Bill of Materials,软件物料清单)及集成到 CI/CD 流水线。
performing-agentless-vulnerability-scanning
配置并执行无代理漏洞扫描(agentless vulnerability scanning),利用网络协议、云快照分析和基于 API 的发现方式评估系统安全,无需在端点安装 Agent。