CrowdSec 主动防御实战:跨网协作的威胁情报与联动封禁


总有一些攻击,是一座孤岛式的 fail2ban 反应不过来的。fail2ban 的思路是"我这一台看见了,就把你封了",但它看不见整个互联网上别人也被同一批攻击者扫过的事实。CrowdSec 换了一个角度:把分散在世界各地服务器上观察到的攻击行为,汇成一个共享的威胁情报池,让"我在上海这台 VPS 上看到的扫描,能帮你封掉同一批 IP 在别处的试探"。这篇讲清 CrowdSec 的架构、怎么部署、怎么把它接进防火墙与反代,以及如何控制误杀的边界——它比单纯的 fail2ban 多出来的,是"协作"和"社区情报"这两手。

一、CrowdSec 和 fail2ban 的分工:本地处置 + 社区情报

CrowdSec 并不是简单地"换一个 fail2ban",它的架构把"观察 → 判断 → 处置 → 共享"拆成了独立组件。一组叫 agent 的进程在所有被保护的机器上采集日志,用一套"场景(scenario)"去识别恶意行为(比如 5 分钟内有 20 次失败的 SSH 登录、Nginx 报错 429/403 密集出现)。识别出恶意行为后,产生一个"决策(decision)",接下来由"处置组件(bouncer)"去执行封禁。而最特别的一环是:这些被标记的恶意 IP 会通过 CTI(Cyber Threat Intelligence)上报去重后汇入社区威胁情报,同时也把社区里别人封禁过的 IP 拉下来供本地参考。

这个分工的价值在于"三层解耦":日志采集、行为判断、实际封禁分别是独立组件,你可以只换某一层的实现而不动整条链。相比 fail2ban 把所有逻辑缝在一起,CrowdSec 的模块化让"换一个数据源""加一个封禁渠道"都更容易。用一个比喻:fail2ban 是"我看见脚往我这抬,就关门",CrowdSec 是"全世界很多房间都连着一张地图,谁在这边闹事,地图上会标出来,各处都能提前关门"。

二、部署:把 CrowdSec 装到一台服务器上

CrowdSec 官方提供 apt/Docker 安装方式。装完之后,它默认就带了对 SSH、Nginx、常见日志的安全场景。Linux 上一条命令安装:

curl -s https://install.crowdsec.net | sudo sh
# 安装 agent 后,用 cscli 管理服务与集合
sudo cscli collections install crowdsecurity/linux
sudo cscli collections install crowdsecurity/nginx
sudo systemctl restart crowdsec

# 看当前状态:收集的日志、识别的恶意行为、本机决策
sudo cscli metrics
sudo cscli decisions list

安装后的重点是用 cscli 这个命令行管理工具去理解"它现在看见了什么":cscli alerts list 看告警,cscli decisions list 看当前生效的封禁,cscli scenarios list 看加载了哪些行为检测场景。很多误配问题的根源是"场景没被正确加载"(比如 Nginx 日志路径和采集器对不上),所以第一步不是急着接 bouncer,而是先确认 agent 真的在正确解析日志——用 cscli logs inspect 验证采集是否命中。

三、真正封禁:bouncer 才是动手的那只手

agent 只负责"识别并打标",实际封禁 IP 要靠 bouncer。不同环境有不同的 bouncer:最常见的是 firewall bouncer(往系统的 nftables/ipset 里写封禁规则,直接把封禁落到内核防火墙)、crowdsec-nginx-bouncer(让 Nginx 直接基于 CrowdSec 决策拒绝请求)、HTTP bouncer(加在反代前,返回 403)等。以一台 VPS 上最常用的 firewall bouncer 为例:

# 安装 firewall bouncer,它在系统 nftables 层面执行封禁
sudo apt install crowdsec-firewall-bouncer-nftables
# 添加一个 bouncer 授权,拿到 API key 填进配置文件
sudo cscli bouncers add my-firewall-bouncer
sudo systemctl enable --now crowdsec-firewall-bouncer

# 手动加一条封禁决策看效果(4 小时内封掉该 IP)
sudo cscli decisions add --ip 203.0.113.5 --duration 4h --type ban

把封禁落到 nftables/ipset 的好处是"阻断发生在内核、不占用应用进程",对 DDoS 级流量也能直接丢弃,而 cscli decisions list 则可以随时查看并手动撤掉某条封禁(cscli decisions delete)。如果你主要想保护的是反代后面的 Web 服务,用 crowdsec-nginx-bouncer 或 HTTP bouncer 更贴合,它们让请求在进入业务之前被拒绝,适合放在你前面用 Nginx/Traefik 收口的架构里——这和之前聊的反代系是同一层。

四、社区情报:让"别家的发现"帮到你这台

CrowdSec 相对 fail2ban 最不一样的一手,是"协作式"的威胁情报。当你在某台机器上检测到恶意行为,相关 IP 会匿名化后加入社区共享的信任/黑名单数据;反过来,你的本地决策系统也会定期从社区拉取这些情报,供自己的场景在判断时参考。这意味着一个在别处刚被标记的恶意 IP,可能在你这里被识别得更早、拦得更快——它把"单机防御"升级成了"借助全网观察"的主动防御。

实践里需要清楚它的边界:社区情报是"参考因子",帮你更快发现已知的攻击来源;它替代不了你在本机正确采集日志、设置场景和对核心服务的专门防护。想用好就常看 cscli alerts list --since 24h 和 cscli botkeys(若想自定义情报客户端)之类的状态,把社区 feed 和你本机的判断结合起来,而不是简单"全信社区名单一锅端"。

五、别误伤好人:误杀的边界要靠"白名单 + 合适的禁封时长"守住

自动封禁最怕的是"误伤"。把 CDN 出口 IP、自己常用的 VPN/公司 IP 误封,会让正常流量被拒在门外,反而造成更大的服务事故。CrowdSec 提供两个缓解手段:一是白名单——在配置里把可信 IP 段(你自己的出口、CDN、监控源)声明为绝不封禁;二是合理的禁封时长与等级——默认按黑客类型区分,SSH 爆破等用短时(几小时)的 ban,服务器的低值探测用更短的处理,避免"一错就封得回不来"。

# 白名单示例:声明某些 IP 段永不封禁(crowdsec 配置)
allowlists:
  my-trusted:
    cidrs:
      - "203.0.113.0/24"   # 你自己的出口
      - "192.168.0.0/16"

判断边界可以遵循一个原则:先观察、再封禁、保留快速解除的通道。第一次启用 CrowdSec 不要立刻开最严的等级,先以"观察模式 + 短时长"运行几天,看看会不会误判可信流量;确认场景稳定后再收紧到实际封禁。任何时候都要保留手动解除某条封禁的能力——自动防御的价值建立在"可撤销、可控误伤"之上,而不是一味地狠。

结语

CrowdSec 的意义不是"又换一个封禁工具",而是把防御从"我这台单机"扩展到"全网协作":用 agent + 场景识别恶意行为,用 bouncer 执行封禁,用社区 CTI 共享情报,三者可独立运维和解耦。落地时的手法是:先把 agent 和正确的场景装好、确认日志解析准确,再接上合适的 bouncer 真正动手封禁,同时留白名单和合理的禁封时长来守住误伤的边界。把它当作"你观察之眼之外的更多双眼睛"来用,而不是"更激进的封禁器",才是它真正匹配自托管栈的用法。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

Terraform 基础设施即代码实战:用声明式蓝图把多台 VPS 管成工程

PostgreSQL 主从复制与高可用实战:从 WAL 流复制到自动故障切换

评 论
更换验证码