1. 简介

雷池开源版本升级到 9.4.3 后发现调整了防护站点的数量而我配置的二级域名超过了16个,无奈之下考虑了另一个 WAF 方案,通过 NPM 实现反向代理服务,结合 Crowdsec 的安全防护功能实现 WAF 防护。

该方案的难点在于:

  1. 我想保留 NPM 的官网版本不打算用其它的集成版本,主要原因是 Nginx 版本的升级可以保障
  2.  Crowdsec 也使用官网版本,确保安全策略和组件能同步更新
  3. 同时我需要实现 WAF 和操作系统的防火墙功能联动对黑名单中的 IP 地址封禁。集成版本中包含了防火墙联动的功能但是独立的版本没有。所以这个组件直接引用第三方的分享版本

核心组件与职责分工:

Nginx Proxy Manager (nginx):负责对外提供 80/443 Web 访问及反向代理,并将访问日志实时写入宿主机卷。

CrowdSec 核心引擎 (crowdsec):以日志分析(Log Processor)模式运行,通过只读挂载实时消费 NPM 的 access.log,并执行内置 WAF 规则及自定义 Bot 拦截策略。

防火墙联动组件 (firewall-bouncer):通过宿主机网络模式与特权模式(network_mode: host, privileged: true),利用 ipset 与 iptables(绑定在 DOCKER-USER 链上),将 CrowdSec 生成的恶意 IP 决策直接在内核层进行 DROP 拦截。

控制台同步(可选):通过 ENROLL_KEY 环境变量实现与 CrowdSec 官方 Cloud Console 的无缝数据同步和看板展示。

2. 配置步骤

配置仍然使用容器的方案,由于需要联动防火墙能力,所以第三方分享的组件采用 host 网络模式直接使用宿主机的网络能力。

2.1. npm-compse-crowdsec.yaml

version: '3.8'
services:
  nginx:
    image: 'jc21/nginx-proxy-manager:2.16.0'
    container_name: nginx
    restart: unless-stopped
    environment:
      - DISABLE_IPV6=true
    ports:
      - '80:80' # Public HTTP Port
      - '443:443' # Public HTTPS Port
      - '82:81' # Admin Web Port
      # - '21:21' # FTP
    networks:
      - proxy-net
    volumes:
      - /data/nginx-proxy/data:/data
      - /etc/localtime:/etc/localtime:ro
      - /data/nginx-proxy/ssl:/etc/letsencrypt

  crowdsec:
    image: docker.io/crowdsecurity/crowdsec:v1.8.2
    container_name: crowdsec
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    environment:
      - COLLECTIONS=crowdsecurity/nginx crowdsecurity/http-cve
    volumes:
      - /data/nginx-proxy/data/logs:/var/log/nginx:ro
      - /data/nginx-proxy/crowdsec-db:/var/lib/crowdsec/data
      - /data/nginx-proxy/crowdsec-config:/etc/crowdsec
    networks:
      - proxy-net

  firewall-bouncer:
    image: ghcr.io/shgew/cs-firewall-bouncer-docker:stable
    container_name: crowdsec-firewall-bouncer
    restart: unless-stopped
    environment:
      - API_URL=http://crowdsec:8080
      - API_KEY=5PcY+2S+wKTrew8X86DeYtihW1OiKv6lwxPTF8PL9XI
      - BOUNCER_ITERATIVE_BAN=true
      - DOCKER_LOGS=true
      - FIREWALL_BACKEND=iptables   # 适配 Photon OS 的 iptables 规则
    volumes:
      - /data/nginx-proxy/bouncer-config/crowdsec-firewall-bouncer.yaml:/config/crowdsec-firewall-bouncer.yaml:ro
    network_mode: host
    privileged: true

networks:
  proxy-net:
    driver: bridge

2.2. 关键日志采集设置

对应的日志采集文件设置为:/data/nginx-proxy/crowdsec-config/acquis.yaml

{"source": "file", "filename": "/var/log/nginx/*access.log", "labels": {"type": "nginx"}}

2.3. 自定义封禁规则

通过自定义封禁规则禁止 bot 的访问。对应的文件地址/data/nginx-proxy/crowdsec-config/scenarios/block-yisouspider.yaml

type: leaky
name: custom/bad-user-agent-yisou
description: "Detect and ban YisouSpider crawler"
filter: "evt.Meta.http_user_agent contains 'YisouSpider'"
groupby: "evt.Meta.source_ip"
capacity: 2
leakspeed: "10s"
blackhole: "24h"
duration: "24h"
labels:
  service: http
  type: bad-bot
  remediation: true

2.4. 创建 Bouncer 配置目录与文件

/data/nginx-proxy/bouncer-config/crowdsec-firewall-bouncer.yaml

mode: iptables
pid_dir: /var/run/
update_frequency: 10s
daemonize: false
log_mode: stdout
log_dir: /var/log/
log_level: info
api_url: http://127.0.0.1:8080/
api_key: 5PcY+2S+wKTrew8X86DeYtihW1OiKv6lwxPTF8PL9XI
populate_ipset: true
iptables_chains:
  - DOCKER-USER
  - INPUT

3. 日常运维与快速验证指令

#重启并应用所有服务
docker compose -f /data/nginx-proxy/npm-compose-crowdsec.yml up -d --force-recreate

#验证日志解析与规则触发
docker exec -it crowdsec cscli explain --log '[14/Nov/2026:22:33:54 +0800] - - 301 - GET http wiki.waringid.me "/techref/docs/pnpm.html" [Client 123.183.235.43] [Length 166] [Gzip -] [Sent-to 192.168.77.12] "YisouSpider" "-"' --type nginx

#检查当前封禁决策列表
docker exec -it crowdsec cscli decisions list
docker exec -it crowdsec cscli metrics

#安装安全组件
docker exec -it crowdsec cscli collections install crowdsecurity/nginx
docker exec -it crowdsec cscli collections install crowdsecurity/http-cve

#检查本地引擎是否工作
docker exec -it crowdsec cscli machines list

#查看已触发的告警列表
docker exec -it crowdsec cscli alerts list

#查看已加载的场景列表
docker exec -it crowdsec cscli scenarios list

#生成Bouncer API Key
docker exec -it crowdsec cscli bouncers add firewall-bouncer-service

#验证防火墙封禁插件(Bouncer)连接
docker exec -it crowdsec cscli bouncers list

#查看防火墙
iptables -L DOCKER-USER -v -n
docker exec -it crowdsec-firewall-bouncer ipset list crowdsec-blacklists-0

#查看命中情况
iptables -L CROWDSEC_CHAIN -v -n

#查看日志
docker logs -f --tail 50 crowdsec-firewall-bouncer

#查看是否已启用全球情报共享
grep -i "online_api" /data/nginx-proxy/crowdsec-config/config.yaml
docker exec -it crowdsec cscli decisions list

4.  参考

在 CrowdSec 的底层架构设计中,IP 封禁列表(Decisions)是分来源和协议分类管理的。具体的分布情况如下:

crowdsec-blacklists-0:这是本地 CrowdSec 引擎(Local Engine)通过日志检测并触发的 IPv4 黑名单集合(例如自定义的 custom/bad-user-agent-yisou 规则所拉黑的本地爬虫 IP 就存放在这里)。

crowdsec-blacklists-1(及其他后续编号):这是由中央威胁情报(CAPI / CrowdSec Central API)同步过来的全球共享黑名单集合。如果开启了 CAPI 社区情报共享,这里还会包含海量的全球已知恶意 IP。

crowdsec6-blacklists-*:这是对应的 IPv6 黑名单集合(专门用来拦截 IPv6 地址的恶意访问)。

  • 无标签
写评论...