Freeflite/PROBan

GitHub: Freeflite/PROBan

ProBAN 是一款 OPNsense 防火墙插件,通过对恶意 IP 实施随其持续攻击程度而加速增长的渐进式封禁策略,替代传统固定阈值拦截方案。

Stars: 0 | Forks: 0

# ProBAN — 渐进式封禁 **为 OPNsense 设计的针对恶意 IP 的渐进式/抛物线式封禁 —— 包含资源消耗型 tarpit 与 honeypot 重定向。** ProBAN 会监控你的防火墙(以及可选的 Suricata)日志,每当一个 IP 探测你的 WAN 口时,它就会*增加*该 IP 的封禁时长。封禁惩罚会随着每次命中而加速,并在沉寂期间衰减——因此,一个顺手扫描的 IP 只会获得 30 秒的超时,而一个顽固的攻击者则会把自己挖进一个以天、甚至以月为单位计算的封禁深渊中。被封禁的 IP 可以被静默**丢弃 (Drop)**,引入到浪费其时间和 socket 连接的 **tarpit** 中,或者重定向到你指定端口上的 **honeypot**——所有这些都可以在 **Reporting → ProBAN** 的实时仪表板中呈现。 ![ProBAN 设置](https://static.pigsec.cn/wp-content/uploads/repos/cas/60/60a049c2ba4b3b14b397013dc725cee8e2e301063c72811a91da37345da41b9f.png) ## 为什么需要它 固定层级的 fail2ban 式拦截会将那个由于手误输入错了一次 SSH 密码的人,与每天狂扫 Telnet 10,000 次的僵尸网络同等对待。ProBAN 是**渐进式的**:惩罚会自动适配其持久度,无需调整任何层级。 ## 封禁机制是如何运作的 每个违规者都有一个**封禁余额**(以秒为单位): - **每次命中都会增长** —— 包括在它们已经被屏蔽*之后*发生的命中(记录在案的 drop 规则会将这些反馈进来)。第 `n` 次命中的增量为 `step × multiplier^(n-1)`,并设置了可配置的上限。 - **在沉寂期间呈线性衰减** —— 每个时间间隔固定衰减一定量(默认每 60 秒衰减 30 秒)。保持安静,你的刑期就会慢慢流失;不断敲门,它就会加速增长。 - **当余额 > 0 时执行屏蔽。** 这就是“抛物线”形状的由来:在遭受主动攻击时向上加速增长,在攻击者放弃时则呈线性衰减。偶尔扫描一次的 IP 一分钟内就会解除限制;而不依不饶的扫描者将被钉在最大封禁额度上并长期滞留。 ## 对被封禁 IP 的处置 —— 三种动作,一个设置 | 动作 | 行为 | |---|---| | **Drop** | 静默黑洞(默认)。 | | **Tarpit** | 重定向到一个零窗口 TCP tarpit,它会接受、拖延并保持连接 —— 消耗攻击者的时间和文件描述符,同时从不读取其输入(零解析器攻击面)。 | | **Honeypot** | 重定向选定的服务端口(例如 `22,23,443`),*保留原始端口*,因此它看起来就像一台开着少量服务的被防火墙保护的主机 —— 等待真正的模拟器(Cowrie/T-Pot/honeytrap)介入。 | 模式由 **Port(s)** 字段的选择决定:留空 = honeypot(保留所有端口),填写一个端口 = tarpit(将流量汇聚到该端口),填写逗号分隔列表 = 仅在这些端口上启用 honeypot。 ### 达到最大封禁后 —— “黑洞”(可选) 默认情况下,达到封禁上限的违规者只会停留在 tarpit 中。开启 **blackhole** 后,一旦某个 IP 触及上限,ProBAN 就会将其放入一个 *drop* 集合中停放一段时间——对于已被证明死不悔改的攻击者,没必要在它们身上浪费 tarpit 的 socket 连接——在此期间以加速的速率消耗其封禁余额(在此期间封禁额度停止攀升),然后让其重新回到 tarpit 中继续尝试。继续滥用 → 达到上限 → 再次回到黑洞中。一丝希望,又不断破灭。 两个调节参数(仅限 tarpit 模式):**`blackhole_hours`** —— 决定它们被 drop 多长时间(默认 12 小时)—— 以及 **`blackhole_decay`** —— 决定黑洞中每小时会抵消多少封禁时长(默认 `2h`/小时)。在底层,这是第二个 pf 表(`parabolic_drop`),引擎会将达到上限的违规者路由到该表,并由防火墙钩子进行拦截。 ### IPv6 IPv6 获得了**与 IPv4 相同的待遇** —— drop、tarpit、honeypot *以及* blackhole —— 而不仅仅是简单的拦截。引擎会将 v6 的 SYN 探测(跳过维持 v6 正常运行的 ICMPv6)解析到专用的 `parabolic_block6` 表中;当设置了私有 v6(ULA)tarpit 目标时,`inet6` `rdr` 会像 v4 一样将它们重定向到坑中,并配有 `inet6` 的 blackhole(`parabolic_drop6`)来对付达到封禁上限的违规者。将 v6 目标留空则可保持 v6 仅使用拦截模式。 **基于证据的 /64 聚合。** 一个 v6 攻击者通常控制着整个 /64 网段,并可以无成本地轮换源地址,因此封禁单个 /128 就像在打地鼠——但 /64 也可能是一个*共享的*主机子网,盲目封禁它会误伤无辜的邻居。因此,ProBAN 会先封禁 /128,只有当它在该 /64 中观察到 **≥ N 个不同的**违规者时,才会升级并封禁整个 /64(可配置;`0` = 从不升级)。共享 /64 上的个别恶意租户不会牵连其邻居;而轮换地址的攻击者则会让整个 /64 都落入陷阱。 ## 安全性 —— 设计上防止被武器化 - **锁定反射** —— 重定向目标只能是**私有/LAN/VPN** 地址(RFC1918、loopback、CGNAT、IPv6 ULA)。公共目标会在 UI、API *以及* 引擎层面被拒绝。你永远无法将其变成针对受害者的出站反射大炮。远程 tarpit 通过 VPN 隧道访问(它提供的是一个私有隧道 IP)。 - **防篡改** —— 引擎在每次运行时都会重新检查实时的重定向目标;如果有人手动将防火墙规则修改为 ProBAN 之外的公共 IP,它会清空 block 表并触发仪表板警报。 - **自我保护的白名单** —— 私有范围和 loopback *始终* 不可被封禁,即使从白名单中移除也是如此,因此你不会将自己锁在门外。 ## 仪表板 在 **Reporting → ProBAN** 下:实时违规者数量 / 活动拦截数 / 事件数、可缩放的违规时间轴(5分钟–24小时分辨率,可前后平移)、按严重程度划分的环形图、支持**点击排序**并具备按 IP 下钻功能的违规者表格、目标健康徽章,以及针对每个旋钮(宽限期、步长、乘数、格式如 `1y 2d` 的最大封禁时长、衰减率、blackhole、白名单、数据保留期、受保护端口)的设置面板。 违规者表格支持**分页**(25 / 50 / 100 / 自定义 / 全部行)以及 **IPv4 / IPv6 / 两者** 筛选/切换器。更改页面大小或 IPv 筛选器时,列排序会被保留(针对当前视图,排序和分页在服务端进行协调)。控制控件始终显示在表格上方。 **Protected ports** 设置(逗号或空格分隔)允许你将特定端口(例如 OpenVPN/TCP 或其他服务)从探测和敲门计数中排除。这一点结合更智能的敲门检测(仅当 action=tarpit、目标地址匹配 tarpit 目标 IP 且端口在配置集合中时,才计算 `pass,in`),可以防止合法的入站 TCP 流量触发封禁,同时仍然会对真正的 tarpit 命中进行升级惩罚。基于 UDP 的 VPN(如 WireGuard 等)在设计上对 ProBAN 是不可见的。VPN 隧道 IP 通过内置的 SAFETY 范围 + 白名单进行保护。请参阅下方的兼容性章节。 ## 仓库布局 ``` Makefile pkg-descr # FreeBSD/OPNsense port metadata src/ etc/ inc/plugins.inc.d/proban.inc # service registration + firewall hook (block / rdr+pass) rc.d/proban # rc.d service wrapper (daemon-supervised engine loop) opnsense/ mvc/app/models/OPNsense/ProBAN/ General.xml General.php # settings model -> config.xml (typed, validated) ACL/ Menu/ # access control + Reporting menu entry mvc/app/controllers/.../ProBAN/ # Index + API (Overview, Settings, Service) controllers mvc/app/views/OPNsense/ProBAN/ # Volt dashboard scripts/OPNsense/Parabolic/ # engine.py + supervisor + config.sample.json service/ conf/actions.d/actions_proban.conf # configd actions (start/stop/restart/status/run) templates/OPNsense/ProBAN/ # generates config.json + rc.conf.d from the model docs/images/ # screenshots ``` ## Tarpit 守护进程 — [tinypit](https://github.com/Freeflite/TinyPit) 配套的 tarpit 位于其独立的仓库中:**[TinyPit](https://github.com/Freeflite/TinyPit)** —— 一个小型的 Rust/[tokio](https://tokio.rs) 零窗口 TCP tarpit。它会接受握手,设置一个极小的接收缓冲区,并且**永不读取**——攻击者的探测会填满缓冲区,内核会通告零窗口,他们的协议栈将停滞在 persist 模式中。它只是偶尔零星发送一个字节。受最大连接数和单 IP 来源上限的限制。请在**位于隔离的敌意 DMZ 中的独立主机**上运行它,绝对不要在路由器本身上运行,然后将 ProBAN 的 tarpit 目标指向它。 ## 部署 — 从零到大神 ProBAN 由两个紧密结合的部分组成:**OPNsense 插件**(大脑 —— 监控日志、增加封禁时长、管理防火墙规则)和 **[TinyPit](https://github.com/Freeflite/TinyPit)**(肌肉 —— 位于隔离主机上的微型 tarpit 守护进程,负责拖住被重定向过来的攻击者)。*Drop* 模式只需要插件;*tarpit / honeypot* 模式则需加上 TinyPit。 ### 1. 构建并安装插件 在 OPNsense 主机(或匹配的 FreeBSD 开发虚拟机)上: ``` git clone https://github.com/opnsense/plugins cp -a PROBan plugins/security/proban # drop this repo in as the plugin cd plugins/security/proban make DEVELOPER=1 install # symlink live for iteration # 或: make package && pkg add work/pkg/*.pkg # 构建并安装真正的 .pkg ``` `.pkg` 的 post-install 脚本会注册模型,根据模板渲染 `config.json`,并启动 configd 服务——完全无需手动编辑。 ### 2. 搭建 TinyPit *(仅限 tarpit / honeypot 模式)* TinyPit 是一个敌意流量的磁铁,因此它必须在**脱离**防火墙的地方运行——位于具有**无 LAN 或互联网出口**的隔离 DMZ 中的 LXC/VM(一个被攻陷的 tarpit 必须是一条死胡同)。详情请见 [TinyPit](https://github.com/Freeflite/TinyPit);简短版本如下: ``` # 便携的 static binary — 可在任何 Linux 上运行,无视 glibc: cargo build --release --target x86_64-unknown-linux-musl install -m755 target/x86_64-unknown-linux-musl/release/tinypit /usr/local/bin/tinypit cp tinypit.service /etc/systemd/system/ && mkdir -p /var/log/tinypit systemctl enable --now tinypit # listens [::]:3333, dual-stack ``` 为该主机分配一个 ProBAN 可以访问的私有 IP(例如 honeypot-DMZ 的 `10.66.66.10`)。*远程* TinyPit 也可以正常工作——通过 VPN 隧道访问它即可;其私有隧道 IP 可以通过反射锁定检查。 ### 3. 将它们连接在一起 在 **Reporting → ProBAN → Settings** 中: - **Enable**,并将 **WAN interface** 设置为你的物理上行链路(不要选 WireGuard iface)。 - **Action → Tarpit**(或 Honeypot);将 **Target IP** 设置为 TinyPit 主机的地址,**Port(s)** 设置为 `3333`。 *(填一个端口 = tarpit · 逗号分隔列表 `22,23,443` = 保留这些端口的 honeypot · 留空 = 针对所有端口的 honeypot)* - *(可选)* 针对你运行的任何入站 TCP 服务设置 **Protected ports**(例如 `1194, 443`)。 保存。ProBAN 会将模型写入 `config.xml`,重新生成 `config.json`,重启引擎,并且它的 `plugins.inc.d` 钩子会部署 `rdr`,将封禁的 IP 引入 TinyPit——无需手动编辑规则。 ### 4. 查看其实际效果 在一个日志周期内,违规者就会填满仪表板。被封禁的 IP 会被重定向到 TinyPit 中(其 `connections.log` 会填满 ` `),每一次持续的敲门都会重新增加其封禁时长,违规时间轴也会亮起。这就是它的闭环:**插件决定拦截*谁*,TinyPit 消耗*他们*的时间,而敲门记录反馈回来增加刑期。** **VPN 及其他入站 TCP 服务的兼容性** ProBAN 仅作用于 TCP SYN 数据包(见 `proban/ingest.py`)。基于 UDP 的 VPN(WireGuard、IPsec、OpenVPN/UDP)对它来说是不可见的——不会有封禁隧道客户端或计算其握手尝试次数的风险。 对于基于 TCP 的 VPN 服务器(例如基于 TCP 的 OpenVPN)或其他合法的入站 TCP 服务/端口转发: - 在 Settings → Detection sources 中使用 **Protected ports** 字段(以逗号或空格分隔,例如 `1194, 443`)。这些端口将在探测记录和“tarpit 敲门”升级惩罚中被完全跳过。 - 敲门检测现在已加入门控机制:一个 `pass,in` 的 TCP SYN 只有在满足以下条件时才会被算作一次 tarpit 敲门: 行为是 tarpit, 记录的目标 IP 匹配已配置的 tarpit 目标(v4 或 v6),且 端口位于 tarpit 集合中(或者在集合空时的完全 honeypot 模式下)。 这可以防止真实用户被当作违规者处理,同时仍能针对实际的 tarpit/honeypot 命中增加封禁时长。 IPv6 完全支持 tarpit/honeypot/blackhole(包括设置了 v6 目标时的 pass/in 敲门检测),逻辑相同,并额外加上了 /64 聚合。 将 WAN 接口设置为你的物理不受信任上行链路(而不是 WireGuard 接口)。VPN 隧道客户端 IP(私有范围或 CGNAT)受内置的 SAFETY 范围 + 你的白名单保护。请参阅 `proban/config.py:SAFETY`。 Protected ports 字段出现在 Settings 下的“Detection sources”中(紧挨着 WAN interface 字段)。仪表板上方的违规者表格还具有 IPv4/IPv6/Both 筛选器以及保留列排序的分页控件(25/50/100/自定义/全部)。 ## 测试 ``` python -m unittest discover -s tests ``` 引擎的封禁计算逻辑是纯函数,并且其写入数据库的路径(`record` / `decay_pass` / `enforce`)将时间戳作为参数接收,因此测试套件是确定性的,且不需要 OPNsense 或 pf。它涵盖了渐进式增长曲线(宽限期 + `step × mult^(n-1)` + 最大上限)、线性与 blackhole 加速衰减的对比、私有目标的反射锁定、双表(`parabolic_block` / `parabolic_drop`)路由、受保护端口 + 更智能的(感知目标/端口的)敲门检测、v4/v6 摄取以及 IPv6 /64 聚合(共享子网安全保障 + 轮换捕获)外加 v6 的 tarpit/blackhole 拆分。分页和 IPv 筛选通过 API + JS 层进行测试。 ## 状态与路线图 目前已实现的功能:渐进式引擎、仪表板、drop/tarpit/honeypot 强制执行、达到上限后的 blackhole 升级、反射锁定、防篡改机制、健康检查。 现已采用标准的 OPNsense 方式进行集成 —— **已在 OPNsense 26.1 上验证通过**: - [x] Config → **模型 XML**(`config.xml` 中包含类型化字段 + 验证) - [x] 引擎 → 使用 **configd/rc.d 服务** 而不是 cron 任务 - [x] 从**模板**生成 `config.json`(引擎直接读取,无需改动) - [x] 防火墙集成由 **`plugins.inc.d` 钩子**全权负责(外部别名 + block / rdr+pass),不存储 UUID - [x] 用于真正 FreeBSD port 的 `Makefile` / `pkg-descr` - [x] 已在 OPNsense 26.1 上进行线上验证 —— 包括模型加载、模板渲染、服务生命周期、防火墙钩子规则生成(block + `rdr pass`)以及仪表板 API - [x] Tarpit 守护进程拆分至其独立仓库 ([TinyPit](https://github.com/Freeflite/TinyPit)) - [x] 可作为真正的 `.pkg` 构建并安装(`make package` → `pkg add`;post-install 会迁移模型并重新加载 configd/templates) - [x] 引擎的自动化测试 (25) —— 封禁计算逻辑、线性 + blackhole 加速衰减、渐进式增长、v4/v6 解析、双表路由、**IPv6 /64 聚合 + v6 tarpit/blackhole 拆分**(见 [测试](#testing)) - [x] **IPv6 tarpit 对齐** —— v6 获得了与 v4 相同的 drop/tarpit/honeypot/blackhole 流程(`inet6` `rdr` + `parabolic_block6` / `parabolic_drop6`),并具有**基于证据的 /64 聚合**(封禁 /128s,仅在出现 *N* 个不同的违规者时才升级到整个 /64,从而确保共享托管 /64 不会牵连其邻居)。已在 OPNsense 26.1 上通过 ULA honeypot DMZ 进行线上验证。 - [x] 支持 i18n —— 每个仪表板字符串都包装在 `lang._()` 中(JS 通过带有可重新排序占位符的翻译查找表);模型/菜单/ACL 自动提取;汇入 `make translate` / Weblate - [ ] (未来某天)联合滥用情报:通过 mTLS 报告给中央聚合器 + 共享信誉订阅源 ## 许可证 BSD 2-Clause —— 见 [LICENSE](LICENSE)。 **如果用于任何衍生作品、产品、软件包或发行版,必须注明出自 [github.com/Freeflite/ProBAN](https://github.com/Freeflite/PROBan)**。
标签:IP 地址批量处理, IP封禁, OPNsense, Tarpit, 可视化界面, 插件系统, 网络安全, 蜜罐, 证书利用, 进程监控, 逆向工具, 防御自动化, 防火墙, 隐私保护