# 使用 CrowdSec 防护 Nginx 恶意扫描与 SSH 爆破
本文记录一次在 Linux VPS 上部署 CrowdSec 的过程,目标是防护常见的 SSH 暴力破解、Nginx 恶意扫描、HTTP CVE 探测和部分异常请求行为。
环境大致如下:
```text
系统:Ubuntu / Debian 系
Web 服务:Nginx
防火墙:UFW + iptables
安全工具:CrowdSec
Bouncer:crowdsec-firewall-bouncer-iptables
1. CrowdSec 是什么?
CrowdSec 可以理解为一个现代化的 Fail2ban。
它的核心工作流程是:
读取日志
↓
解析日志
↓
识别攻击行为
↓
产生封禁决策 decision
↓
交给 bouncer 执行封禁
例如:
SSH 多次登录失败
Nginx 被扫描 /.env
访问 /.git/config
探测 /wp-login.php
尝试访问 phpMyAdmin
HTTP DoS 行为
常见 CVE 探测
CrowdSec 本身负责“判断谁是攻击者”,但真正执行封禁的是 bouncer。
常见组件包括:
crowdsec 主程序,负责分析日志
cscli 命令行管理工具
crowdsec-firewall-bouncer 防火墙封禁组件
crowdsec-nginx-bouncer Nginx 层封禁组件,可选
collections 规则包,例如 nginx、http-cve、http-dos
本文采用的是更通用、更稳妥的方式:
CrowdSec + firewall bouncer + iptables
2. 为什么没有使用 crowdsec-nginx-bouncer?
一开始尝试安装 Nginx bouncer:
sudo apt install nginx lua5.1 libnginx-mod-http-lua luarocks gettext-base lua-cjson
sudo apt install crowdsec-nginx-bouncer
但遇到了错误:
Package 'libnginx-mod-http-lua' has no installation candidate
crowdsec-nginx-bouncer : Depends: libnginx-mod-http-lua but it is not installable
这通常说明当前系统源里没有可安装的 Nginx Lua 模块,常见原因包括:
系统版本较旧
Nginx 不是从系统官方源安装
使用了 nginx.org 官方源
apt 源不完整
模块包与当前 Nginx 版本不匹配
所以这里不继续折腾 Nginx bouncer,而是使用 firewall bouncer。
这种方案同样可以实现:
CrowdSec 分析 Nginx access.log
↓
识别恶意扫描 IP
↓
通过 iptables 封禁该 IP
对普通 VPS 来说已经足够实用。
3. 安装 CrowdSec
添加 CrowdSec 官方仓库并安装:
curl -s https://install.crowdsec.net | sudo sh
sudo apt update
sudo apt install crowdsec
启动 CrowdSec:
sudo systemctl enable --now crowdsec
查看状态:
sudo systemctl status crowdsec
查看版本:
sudo cscli version
4. 查看当前 CrowdSec 是否在工作
执行:
sudo cscli metrics
如果刚安装完,可能只能看到类似:
Acquisition Metrics
Source Lines read Lines parsed Lines unparsed
file:/var/log/auth.log 14 - 14
file:/var/log/kern.log 7 - 7
file:/var/log/syslog 7 - 7
这说明 CrowdSec 当前只读取了系统日志,还没有读取 Nginx 日志。
如果你想防护 Nginx 恶意扫描,就必须把 Nginx access log 接入 CrowdSec。
5. 安装 Nginx 防护规则
安装 Nginx collection:
sudo cscli collections install crowdsecurity/nginx
建议再安装 HTTP CVE 和 HTTP DoS 相关规则:
sudo cscli collections install crowdsecurity/http-cve
sudo cscli collections install crowdsecurity/http-dos
查看已安装的 collection:
sudo cscli collections list
查看场景规则:
sudo cscli scenarios list
查看解析器:
sudo cscli parsers list
6. 配置 CrowdSec 读取 Nginx 日志
先确认 Nginx 日志存在:
ls -lh /var/log/nginx/
常见日志路径为:
/var/log/nginx/access.log
/var/log/nginx/error.log
创建 CrowdSec 的 Nginx 日志采集配置:
sudo tee /etc/crowdsec/acquis.d/nginx.yaml > /dev/null <<'EOF'
filenames:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
labels:
type: nginx
EOF
重启 CrowdSec:
sudo systemctl restart crowdsec
再次查看 metrics:
sudo cscli metrics
正常情况下,Acquisition Metrics 里应该出现:
file:/var/log/nginx/access.log
file:/var/log/nginx/error.log
如果没有出现,排查这几个点:
Nginx 日志路径是否正确
Nginx 是否真的在写 access.log
CrowdSec 是否有权限读取日志
nginx.yaml 的缩进是否正确
是否重启了 crowdsec 服务
7. 使用 UFW 和 iptables 时怎么选 bouncer?
我的服务器已经启用了 UFW,并且底层是 iptables。
UFW 和 CrowdSec 并不冲突:
UFW:管理基础端口开放,例如 22、80、443
CrowdSec:分析日志,判断恶意 IP
firewall bouncer:把恶意 IP 写入 iptables 进行封禁
查看 UFW 状态:
sudo ufw status verbose
查看 iptables 版本:
sudo iptables -V
如果确认使用 iptables,可以安装 iptables 版 bouncer:
sudo apt install crowdsec-firewall-bouncer-iptables
启动:
sudo systemctl enable --now crowdsec-firewall-bouncer
查看状态:
sudo systemctl status crowdsec-firewall-bouncer
查看 bouncer 是否注册成功:
sudo cscli bouncers list
8. UFW 规则仍然照常使用
例如:
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status numbered
不建议用 UFW 手动维护 CrowdSec 的动态封禁 IP。
正确分工是:
UFW:固定开放端口
CrowdSec bouncer:动态封禁恶意 IP
9. 测试 CrowdSec 是否能产生封禁决策
手动添加一个测试封禁 IP。
这里使用文档测试网段 IP,不要随便封自己的真实 IP:
sudo cscli decisions add --ip 203.0.113.123 --duration 10m --reason "manual test"
查看封禁决策:
sudo cscli decisions list
正常会看到类似:
203.0.113.123 ban manual test
这一步说明 CrowdSec 已经产生了 decision。
10. 测试 iptables bouncer 是否真正执行封禁
查看 iptables 规则:
sudo iptables -S | grep -i crowdsec
或者:
sudo iptables -L -n -v | grep -i crowdsec
如果 bouncer 使用 ipset,也可以查看:
sudo ipset list | grep -A 20 -i crowdsec
正常情况下,应该能看到类似:
CROWDSEC_CHAIN
crowdsec-blacklists
203.0.113.123
如果能在 iptables 或 ipset 中看到测试 IP,就说明 bouncer 已经正常接管防火墙封禁。
删除测试封禁:
sudo cscli decisions delete --ip 203.0.113.123
再次确认:
sudo cscli decisions list
sudo iptables -S | grep 203.0.113.123
sudo ipset list | grep 203.0.113.123
没有输出就说明测试封禁已经删除。
11. 谨慎测试封禁自己的公网 IP
如果要做真实连通性测试,可以临时封自己的 IP。
先查看当前 SSH 来源 IP:
echo $SSH_CLIENT
输出的第一个 IP 通常就是你的公网 IP。
然后开一个新的 SSH 窗口保持备用,不要关闭当前连接。
执行:
sudo cscli decisions add --ip 你的公网IP --duration 1m --reason "self test"
然后尝试新开一个 SSH 连接或访问网站,应该会被拦截。
测试完成后可以等待 1 分钟自动恢复,或者立即解封:
sudo cscli decisions delete --ip 你的公网IP
注意:
不要关闭当前 SSH 窗口
不要设置太长封禁时间
不要在没有其他登录方式的情况下测试
12. 测试 Nginx 恶意扫描检测
如果已经接入了 Nginx 日志,可以模拟一些常见扫描路径:
curl -I http://你的域名/.env
curl -I http://你的域名/.git/config
curl -I http://你的域名/wp-login.php
curl -I http://你的域名/phpmyadmin
然后查看告警:
sudo cscli alerts list
查看封禁决策:
sudo cscli decisions list
查看 CrowdSec 处理日志情况:
sudo cscli metrics
实时查看 CrowdSec 日志:
sudo journalctl -u crowdsec -f
注意:CrowdSec 不一定因为一次请求就立刻封禁。它通常会根据规则,在一定时间窗口内检测多次可疑行为后才触发封禁。
13. 常用管理命令
查看 CrowdSec 服务状态:
sudo systemctl status crowdsec
查看 firewall bouncer 状态:
sudo systemctl status crowdsec-firewall-bouncer
查看 CrowdSec 指标:
sudo cscli metrics
查看 bouncer:
sudo cscli bouncers list
查看告警:
sudo cscli alerts list
查看封禁列表:
sudo cscli decisions list
手动封禁 IP:
sudo cscli decisions add --ip 1.2.3.4 --duration 1h --reason "manual ban"
手动解封 IP:
sudo cscli decisions delete --ip 1.2.3.4
更新 Hub:
sudo cscli hub update
sudo cscli hub upgrade
sudo systemctl restart crowdsec
查看 CrowdSec 日志:
sudo journalctl -u crowdsec -f
查看 bouncer 日志:
sudo journalctl -u crowdsec-firewall-bouncer -f
14. 如果服务器在 Cloudflare 或反向代理后面
如果 Nginx access.log 记录的是 Cloudflare IP 或反代 IP,而不是真实访客 IP,那么 CrowdSec 可能会误判,甚至封禁 Cloudflare 节点。
需要先让 Nginx 记录真实 IP。
以 Cloudflare 为例,可以在 Nginx 中配置:
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
然后查看 access log:
sudo tail -f /var/log/nginx/access.log
确认日志里出现的是真实用户 IP 后,再让 CrowdSec 分析 Nginx 日志。
15. 建议配合 Nginx 限速
CrowdSec 是“发现攻击后封禁”,Nginx 限速可以在请求进入时就做压制。
在 Nginx 的 http {} 中添加:
limit_req_zone $binary_remote_addr zone=global_limit:10m rate=10r/s;
在站点的 server {} 或 location / {} 中添加:
limit_req zone=global_limit burst=30 nodelay;
检查配置:
sudo nginx -t
重载 Nginx:
sudo systemctl reload nginx
这样可以进一步降低高频请求、恶意扫描、简单 DoS 对服务器的影响。
16. 最小可用部署命令汇总
如果是 Ubuntu/Debian + Nginx + UFW + iptables,可以参考下面这组命令:
curl -s https://install.crowdsec.net | sudo sh
sudo apt update
sudo apt install -y crowdsec
sudo systemctl enable --now crowdsec
sudo cscli collections install crowdsecurity/nginx
sudo cscli collections install crowdsecurity/http-cve
sudo cscli collections install crowdsecurity/http-dos
sudo tee /etc/crowdsec/acquis.d/nginx.yaml > /dev/null <<'EOF'
filenames:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
labels:
type: nginx
EOF
sudo systemctl restart crowdsec
sudo apt install -y crowdsec-firewall-bouncer-iptables
sudo systemctl enable --now crowdsec-firewall-bouncer
sudo cscli metrics
sudo cscli bouncers list
sudo cscli decisions list
17. 测试命令汇总
sudo cscli bouncers list
sudo cscli decisions add --ip 203.0.113.123 --duration 10m --reason "manual test"
sudo cscli decisions list
sudo iptables -S | grep -i crowdsec
sudo ipset list | grep -A 20 -i crowdsec
sudo cscli decisions delete --ip 203.0.113.123
sudo cscli decisions list
18. 本次部署结论
最终采用的方案是:
UFW + iptables
CrowdSec 主程序
crowdsecurity/nginx collection
crowdsecurity/http-cve collection
crowdsecurity/http-dos collection
crowdsec-firewall-bouncer-iptables
没有使用:
crowdsec-nginx-bouncer
原因是系统中缺少可安装的:
libnginx-mod-http-lua
而使用 firewall bouncer 已经可以完成大部分公网 VPS 的防护需求。
最终效果:
SSH 爆破:可检测并封禁
Nginx 恶意扫描:可检测并封禁
HTTP CVE 探测:可检测并封禁
部分 HTTP DoS 行为:可检测并封禁
UFW 端口管理:继续正常使用
iptables 动态封禁:由 CrowdSec bouncer 负责
19. 推荐部署顺序
更稳妥的部署顺序是:
第一步:安装 CrowdSec
第二步:安装 nginx / http-cve / http-dos collections
第三步:配置 Nginx access.log 采集
第四步:安装 crowdsec-firewall-bouncer-iptables
第五步:测试手动 decision 是否能进入 iptables
第六步:观察 cscli metrics、alerts、decisions
第七步:再考虑是否加入 Nginx 限速或其他 WAF
这样配置比较清晰,也方便排查问题。
20. 一句话总结
CrowdSec 不是传统意义上的防火墙,而是一个日志分析和攻击识别引擎。
真正执行封禁的是 bouncer。
在普通 VPS 上,比较推荐的组合是:
UFW 管端口
CrowdSec 看日志
firewall bouncer 封 IP
Nginx limit_req 做限速
这套组合简单、稳定、容易回滚,适合用来防 SSH 爆破和 Nginx 恶意扫描。