maxlerebourg/crowdsec-bouncer-traefik-plugin
GitHub: maxlerebourg/crowdsec-bouncer-traefik-plugin
该插件为 Traefik 反向代理集成 CrowdSec 安全引擎,实现基于 IP 声誉的请求拦截与 WAF 应用层防护。
Stars: 809 | Forks: 43



[](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/actions)
[](https://goreportcard.com/badge/github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin)
# Crowdsec Bouncer Traefik 插件
此插件旨在作为 Traefik 插件实现一个 Crowdsec Bouncer。
其目的是使 Traefik 能够根据 IP 的声誉和行为来授权或阻止来自这些 IP 的请求。
Crowdsec 实用程序将提供社区阻止列表,其中包含在 Crowdsec 网络中被高度举报并经验证封禁的 IP。
与 Crowdsec 结合使用时,它将利用本地 API 分析 Traefik 日志,并针对用户/机器人发起的请求做出决策。恶意行为者将根据其针对您网站所使用的模式被予以封禁。
从插件版本 1.2.0 和 Crowdsec 1.6.0 开始支持应用安全(Appsec)功能。
Appsec 组件提供:
- 低成本的虚拟补丁功能。
- 支持您现有的 ModSecurity 规则。
- 将经典 WAF 的优势与 Crowdsec 的高级功能相结合,以实现通常难以完成的高级行为检测。
有关 appsec 的更多信息,请参阅 [Crowdsec 文档](https://doc.crowdsec.net/docs/next/appsec/intro/)。
由 [Crowdsec](https://docs.crowdsec.net/u/bouncers/intro) 提供且受该插件支持的补救措施可以是 `ban` 或 `captcha`。
对于 `ban` 补救措施,用户将在 Traefik 中被阻止(HTTP 403)。
对于 `captcha` 补救措施,用户将被重定向到一个页面以完成验证码挑战。
成功完成后,如果 Crowdsec 仍有需要验证用户行为的决策,该用户将在特定时间段内被予以放行,之后才会被要求重新进行验证。有关更多信息和配置说明,请参见示例 captcha。
目前支持以下 captcha 提供商:
- [hcaptcha](https://www.hcaptcha.com/)
- [recaptcha](https://www.google.com/recaptcha/about/)
- [turnstile](https://www.cloudflare.com/products/turnstile/)
- [自定义/wicketkeeper](https://github.com/a-ve/wicketkeeper)
此插件有 5 种操作模式:
| 模式 | 描述 |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| none | 如果客户端 IP 在封禁列表中,它将收到 HTTP 403 响应。否则,请求将照常继续。所有请求都会调用 Crowdsec LAPI |
| live | 如果客户端 IP 在封禁列表中,它将收到 HTTP 403 响应。否则,请求将照常继续。Bouncer 可以利用本地缓存来减少向 Crowdsec LAPI 发出的请求数量。它将缓存每个发起查询的 IP 的状态。 |
| stream | 流模式允许您仅在本地缓存中保留被封禁的 IP,未命中缓存的每个请求都将被授权。每隔一分钟,缓存将根据 Crowdsec LAPI 的最新信息进行更新。 |
| alone | 独立模式,类似于流模式,但黑名单 IP 是从 CAPI 获取的。每隔 2 小时,缓存将根据 Crowdsec CAPI 的最新信息进行更新。它不包含任何本地封禁的 IP,但可以在没有 crowdsec 服务的情况下工作。 |
| appsec | 禁用 Crowdsec IP 检查,但应用 Crowdsec Appsec 检查。此模式旨在用于在防火墙层级应用了 Crowdsec IP 检查的情况。 |
为了获得最佳性能,推荐使用 `流模式`,决策默认每 60 秒更新一次,这是 Traefik 和 Crowdsec 之间唯一的通信。发生的每一个请求都会命中缓存以进行快速决策。
缓存可以是 Traefik 本地的内存缓存,也可以使用单独的 Redis 实例。
以下是详细介绍每种模式工作原理的 Mermaid 图表:
## 用法
要开始使用,请使用 `docker-compose.yml` 文件。
您可以通过以下命令运行它:
```
make run
```
### 注意
### 变量
- Enabled
- bool
- 默认值:false
- 启用插件
- LogLevel
- string
- 默认值:`INFO`,预期值为:`DEBUG`、`INFO`、`WARN`、`ERROR`
- 日志将写入 `stdout` / `stderr`,或者在提供了 LogFilePath 时写入文件
- LogFormat
- string
- 默认值:`common`,预期值为:`common`、`json`
- 日志格式:`common` 用于传统文本日志,`json` 用于结构化 JSON 日志
- LogFilePath
- string
- 默认值:""
- 写入日志的文件路径,必须可被 Traefik 写入,日志轮转可能需要重启 traefik
- MetricsUpdateIntervalSeconds
- int64
- 默认值:600
- 向 Crowdsec 更新指标的时间间隔(以秒为单位)
- 如果设置为零或更小,则禁用指标收集
- CrowdsecMode
- string
- 默认值:`live`,预期值为:`none`、`live`、`stream`、`alone`、`appsec`
- CrowdsecAppsecEnabled
- bool
- 默认值:false
- 启用 Crowdsec Appsec Server (WAF)。
- CrowdsecAppsecHost
- string
- 默认值:"crowdsec:7422"
- Crowdsec Appsec Server 可用的主机和端口。
- CrowdsecAppsecTlsInsecureVerify
- bool
- 默认值:false
- 禁用对 Appsec 提供的证书的验证
- CrowdsecAppsecTlsCertificateAuthority
- string
- 默认值:""
- 用于验证 Appsec 服务器证书的 PEM 编码证书授权机构(CA)。当为空(且 `crowdsecAppsecTlsInsecureVerify` 为 `false`)时,使用主机的系统信任库。
- CrowdsecAppsecScheme
- string
- 默认值:`CrowdsecLapiScheme` 的值,预期值为:`http`、`https`
- CrowdsecAppsecPath
- string
- 默认值:"/"
- Crowdsec Appsec Server 在此路径上可用。将附加到 CrowdsecAppsecHost。需要以 "/" 结尾。
- CrowdsecAppsecFailureBlock
- bool
- 默认值:true
- 当 Crowdsec Appsec Server 返回 [状态码 500](https://docs.crowdsec.net/docs/next/appsec/protocol#response-code) 时阻止请求。
- CrowdsecAppsecUnreachableBlock
- bool
- 默认值:true
- 当 Crowdsec Appsec Server 无法访问时阻止请求。
- CrowdsecAppsecBodyLimit
- int64
- 默认值:10485760 (= 10MB)
- 仅将前指定数量的字节传输给 Crowdsec Appsec Server。
- CrowdsecAppsecKey
- string
- 默认值:`CrowdsecLapiKey` 的值
- Bouncer 的 Crowdsec AppSec 密钥。
- CrowdsecLapiScheme
- string
- 默认值:`http`,预期值为:`http`、`https`
- CrowdsecLapiHost
- string
- 默认值:"crowdsec:8080"
- Crowdsec LAPI 可用的主机和端口。
- CrowdsecLapiPath
- string
- 默认值:"/"
- Crowdsec LAPI Server 在此路径上可用。将附加到 CrowdsecLapiHost。需要以 "/" 结尾。
- CrowdsecLapiKey
- string
- 默认值:""
- Bouncer 的 Crowdsec LAPI 密钥。
- CrowdsecLapiTlsInsecureVerify
- bool
- 默认值:false
- 禁用对 Crowdsec LAPI 提供的证书的验证
- CrowdsecLapiTlsCertificateAuthority
- string
- 默认值:""
- 用于验证 LAPI 服务器证书的 PEM 编码证书授权机构(CA)。当为空(且 `crowdsecLapiTlsInsecureVerify` 为 `false`)时,使用主机的系统信任库。
- CrowdsecLapiTlsCertificateBouncer
- string
- 默认值:""
- Bouncer 的 PEM 编码客户端证书
- CrowdsecLapiTlsCertificateBouncerKey
- string
- 默认值:""
- Bouncer 的 PEM 编码客户端私钥
- ClientTrustedIPs
- string
- 默认值:[]
- 信任的客户端 IP 列表,它们将绕过来自 bouncer 或缓存的任何检查(适用于局域网或 VPN IP)
- RemediationHeadersCustomName
- string
- 默认值:""
- 当请求由插件处理时,您希望在响应中看到的标头名称(标头的可能值包括 `ban`、`captcha` 或 `solved-captcha`)
- ForwardedHeadersCustomName
- string
- 默认值:"X-Forwarded-For"
- 应从中检索客户端真实 IP 的标头名称
- ForwardedHeadersTrustedIPs
- []string
- 默认值:[]
- 位于 traefik 前端的受信任代理的 IP 列表(例如:Cloudflare)
- RedisCacheEnabled
- bool
- 默认值:false
- 启用 Redis 缓存而非内存缓存
- RedisCacheHost
- string
- 默认值:"redis:6379"
- Redis 服务的主机名和端口
- RedisCachePassword
- string
- 默认值:""
- Redis 服务的密码
- RedisCacheDatabase
- string
- 默认值:""
- 为 Redis 服务选择数据库
- RedisCacheUnreachableBlock
- bool
- 默认值:true
- 当 Redis 无法访问时阻止请求(如果 Redis 无法访问,每个请求将增加 1 秒的延迟)
- HTTPTimeoutSeconds
- int64
- 默认值:10
- 联系 Crowdsec LAPI 的默认超时时间(以秒为单位)
- UpdateIntervalSeconds
- int64
- 默认值:60
- 仅在 `stream` 模式下使用,从 LAPI 获取黑名单 IP 的请求之间的间隔
- UpdateMaxFailure
- int64
- 默认值:0
- 仅在 `stream` 和 `alone` 模式下使用,在阻止流量之前我们无法连接到 Crowdsec 的最长时间(设置为 -1 表示永不阻止)
- StreamStartupBlock
- bool
- 默认值:true
- 仅在 `stream` 和 `alone` 模式下使用,控制初始流更新是在插件初始化期间同步还是异步运行
- 当为 `true` 时,插件初始化会等待 Crowdsec 准备就绪后再开始提供流量服务。
- **警告**:当为 `false` 时,在第一次流同步完成之前,所有请求都会绕过补救措施——在这段窗口期内,被封禁的 IP 将被允许通过。仅当启动时的可用性比启动时阻止请求更重要时,才禁用此选项。
- DefaultDecisionSeconds
- int64
- 默认值:60
- 仅在 `live` 模式下使用,最大决策持续时间
- RemediationStatusCode
- int
- 默认值:403
- 封禁用户(非 captcha)的 HTTP 状态码
- CrowdsecCapiMachineId
- string
- 仅在 `alone` 模式下使用,Crowdsec CAPI 的登录名
- CrowdsecCapiPassword
- string
- 仅在 `alone` 模式下使用,Crowdsec CAPI 的密码
- CrowdsecCapiScenarios
- []string
- 仅在 `alone` 模式下使用,Crowdsec CAPI 的场景
- CaptchaProvider
- string
- 用于验证 captcha 的提供商,预期值为:`hcaptcha`、`recaptcha`、`turnstile` 或 `custom`
- CaptchaCustomJsURL
- string
- 如果 CaptchaProvider 为 `custom`,则用于在 HTML 中加载挑战的 URL(对于 hcaptcha:`https://hcaptcha/1/api.js`)
- CaptchaCustomValidateURL
- string
- 如果 CaptchaProvider 为 `custom`,则用于验证挑战的 URL(对于 hcaptcha:`https://api.hcaptcha.com/siteverify`)
- CaptchaCustomKey
- string
- 如果 CaptchaProvider 为 `custom`,则用于设置由 captcha 提供商使用的 div 的类名(对于 hcaptcha:`h-captcha`)
- CaptchaCustomResponse
- string
- 如果 CaptchaProvider 为 `custom`,则用于设置从 captcha.html 到 Traefik 的 POST 正文中的字段(对于 hcaptcha:`h-captcha-response`)
- CaptchaSiteKey
- string
- captcha 提供商的站点密钥
- CaptchaSecretKey
- string
- captcha 提供商的站点密钥
- CaptchaGracePeriodSeconds
- int64
- 默认值:1800(= 30 分钟)
- 验证 captcha 后,如果 Crowdsec 决策仍然有效,则在进行新验证之前的宽限期
- CaptchaHTMLFilePath
- string
- 默认值:/captcha.html
- 存储 captcha 模板的路径
- BanHTMLFilePath
- string
- 默认值:""
- 存储封禁 HTML 文件的路径(默认为空 ""=禁用)
- TraceHeadersCustomName
- string
- 默认值:""
- 要注入到封禁 HTML 响应中的值的请求标头名称(默认为空 ""=禁用)
### 配置
对于每个插件,Traefik 静态配置必须定义模块名称(这与 Go 包的常规做法一致)。
以下声明(此处以 YAML 给出)定义了一个插件:
```
# 静态配置
experimental:
plugins:
bouncer:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: vX.Y.Z # To update
```
```
# 简化动态配置
http:
routers:
my-router:
rule: host(`whoami.localhost`)
service: service-foo
entryPoints:
- web
middlewares:
- crowdsec
services:
service-foo:
loadBalancer:
servers:
- url: http://127.0.0.1:5000
middlewares:
crowdsec:
plugin:
bouncer:
enabled: true
logLevel: DEBUG
crowdsecMode: live
crowdsecLapiKey: privateKey-foo
crowdsecLapiHost: crowdsec:8080
```
```
# 完全动态配置
http:
routers:
my-router:
rule: host(`whoami.localhost`)
service: service-foo
entryPoints:
- web
middlewares:
- crowdsec
services:
service-foo:
loadBalancer:
servers:
- url: http://127.0.0.1:5000
middlewares:
crowdsec:
plugin:
bouncer:
enabled: false
logLevel: DEBUG
logFormat: common
LogFilePath: ""
updateIntervalSeconds: 60
updateMaxFailure: 0
streamStartupBlock: true
defaultDecisionSeconds: 60
remediationStatusCode: 403
httpTimeoutSeconds: 10
crowdsecMode: live
crowdsecAppsecEnabled: false
crowdsecAppsecScheme: ""
crowdsecAppsecHost: crowdsec:7422
crowdsecAppsecPath: "/"
crowdsecAppsecFailureBlock: true
crowdsecAppsecUnreachableBlock: true
crowdsecAppsecBodyLimit: 10485760
crowdsecLapiKey: privateKey-foo
crowdsecLapiScheme: http
crowdsecLapiHost: crowdsec:8080
crowdsecLapiPath: "/"
crowdsecLapiTLSInsecureVerify: false
crowdsecCapiMachineId: login
crowdsecCapiPassword: password
crowdsecCapiScenarios:
- crowdsecurity/http-path-traversal-probing
- crowdsecurity/http-xss-probing
- crowdsecurity/http-generic-bf
forwardedHeadersTrustedIPs:
- 10.0.10.23/32
- 10.0.20.0/24
clientTrustedIPs:
- 192.168.1.0/24
forwardedHeadersCustomName: X-Custom-Header
remediationHeadersCustomName: cs-remediation
redisCacheEnabled: false
redisCacheHost: "redis:6379"
redisCachePassword: password
redisCacheDatabase: "5"
redisCacheUnreachableBlock: true
crowdsecLapiTLSCertificateAuthority: |-
-----BEGIN CERTIFICATE-----
MIIEBzCCAu+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
...
Q0veeNzBQXg1f/JxfeA39IDIX1kiCf71tGlT
-----END CERTIFICATE-----
crowdsecLapiTLSCertificateBouncer: |-
-----BEGIN CERTIFICATE-----
MIIEHjCCAwagAwIBAgIUOBTs1eqkaAUcPplztUr2xRapvNAwDQYJKoZIhvcNAQEL
...
RaXAnYYUVRblS1jmePemh388hFxbmrpG2pITx8B5FMULqHoj11o2Rl0gSV6tHIHz
N2U=
-----END CERTIFICATE-----
crowdsecLapiTLSCertificateBouncerKey: |-
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAtYQnbJqifH+ZymePylDxGGLIuxzcAUU4/ajNj+qRAdI/Ux3d
...
ic5cDRo6/VD3CS3MYzyBcibaGaV34nr0G/pI+KEqkYChzk/PZRA=
-----END RSA PRIVATE KEY-----
captchaProvider: hcaptcha
captchaSiteKey: FIXME
captchaSecretKey: FIXME
captchaGracePeriodSeconds: 1800
captchaHTMLFilePath: /captcha.html
banHTMLFilePath: /ban.html
traceHeadersCustomName: X-Request-ID
metricsUpdateIntervalSeconds: 600
```
#### 使用文件内容填充变量
`CrowdsecLapiTlsCertificateBouncerKey`、`CrowdsecLapiTlsCertificateBouncer`、`CrowdsecLapiTlsCertificateAuthority`、`CrowdsecAppsecTlsCertificateAuthority`、`CrowdsecCapiMachineId`、`CrowdsecCapiPassword`、`CrowdsecLapiKey`、`CrowdsecAppsecKey`、`CaptchaSiteKey`、`CaptchaSecretKey` 和 `RedisCachePassword` 可以以原始内容的形式提供,或者通过 Traefik 可以读取的文件路径提供。
如果为同一变量同时提供了内容和文件,则将优先使用文件变量。
格式为:
- 内容:VariableName: XXX
- 文件:VariableNameFile: /path
#### 通过 LAPI 进行身份验证
您可以使用 LAPIKEY 或通过使用客户端证书来对 LAPI 进行身份验证。
请查看下面有关每个选项的更多详细信息。
#### 生成 LAPI KEY
您可以为 LAPI 生成一个 crowdsec API 密钥。
您可以在此处遵循文档:[docs.crowdsec.net/docs/user_guides/lapi_mgmt](https://docs.crowdsec.net/docs/user_guides/lapi_mgmt)
```
docker compose -f docker-compose-local.yml up -d crowdsec
docker exec crowdsec cscli bouncers add crowdsecBouncer
```
此 LAPI 密钥必须设置在 docker-compose.yml 中标记为 FIXME-LAPI-KEY 的地方
```
..
whoami:
labels:
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapikey=FIXME-LAPI-KEY"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapischeme=http"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdseclapihost=crowdsec:8080"
..
crowdsec:
environment:
BOUNCER_KEY_TRAEFIK: FIXME-LAPI-KEY
```
注意:
然后您可以运行所有容器:
```
docker compose up -d
```
#### 使用证书与 CrowdSec 进行身份验证
您可以查看 `examples/tls-auth` 中的示例,了解如何使用客户端证书通过 LAPI 进行身份验证。
在这种情况下,与 LAPI 的通信必须通过 HTTPS 进行。
在 `examples/tls-auth/gencerts.sh` 中提供了一个用于生成证书的脚本,并且它必须与用于创建 PKI 的输入位于同一目录中。
#### 使用 HTTPS 与 LAPI 通信
将 `crowdsecLapiScheme` 设置为 `https`。然后插件会验证 Crowdsec 的服务器证书。有三个选项:
- **公开受信任的证书**(例如:位于反向代理后面的 Let's Encrypt):将 `crowdsecLapiTLSCertificateAuthority` 留空,并将 `crowdsecLapiTLSInsecureVerify` 设为 `false`。插件将回退到主机的系统信任库(`traefik` 镜像附带了 `ca-certificates`)。
- **私有/自签名 CA**:将 `crowdsecLapiTLSCertificateAuthority`(或 `…File`)设置为签署 Crowdsec 服务器证书的 PEM 编码 CA。
- **完全跳过验证**(不建议用于生产环境):将 `crowdsecLapiTLSInsecureVerify` 设置为 `true`。
Crowdsec 必须在 HTTPS 上进行监听才能使其工作。
请参阅 [tls-auth 示例](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/tls-auth/README.md) 或官方文档:[docs.crowdsec.net/docs/local_api/tls_auth/](https://docs.crowdsec.net/docs/local_api/tls_auth/)
#### 使用 HTTPS 与 Appsec 通信
将 `crowdsecAppsecScheme` 设置为 `https`。与 LAPI 相同的三个选项,前缀改为 `crowdsecAppsec…` 而不是 `crowdsecLapi…`:CA 为空 + 安全验证将回退到系统信任库,自定义 CA 将绑定到您的私有 PKI,而 `crowdsecAppsecTLSInsecureVerify=true` 将完全跳过验证。
目前,AppSec 组件不支持 mTLS 身份验证。
#### 手动将 IP 添加到阻止列表(用于测试目的)
```
docker compose up -d crowdsec
docker exec crowdsec cscli decisions add --ip 10.0.0.10 -d 10m # this will be effective 10min
docker exec crowdsec cscli decisions remove --ip 10.0.0.10
docker exec crowdsec cscli decisions add --ip 10.0.0.10 -d 10m -t captcha # this will return a captcha challenge
docker exec crowdsec cscli decisions remove --ip 10.0.0.10 -t captcha
```
### 示例
#### 1. 位于其他代理服务(例如:cloudflare)之后 [examples/behind-proxy/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/behind-proxy/README.md)
#### 2. 使用 Redis 作为外部共享缓存 [examples/redis-cache/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/redis-cache/README.md)
#### 3. 使用不会受 crowdsec 过滤的受信任 IP(例如:局域网或 VPN) [examples/trusted-ips/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/trusted-ips/README.md)
#### 4. 在单个虚拟机中使用作为二进制文件安装的 Crowdsec 和 Traefik [examples/binary-vm/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/binary-vm/README.md)
#### 5. 使用 HTTPS 通信和 TLS 身份验证与 Crowdsec 进行交互 [examples/tls-auth/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/tls-auth/README.md)
#### 6. 在 Kubernetes 中使用 Crowdsec 和 Traefik [examples/kubernetes/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/kubernetes/README.md)
#### 7. 在没有 Crowdsec 的独立模式下使用 Traefik [examples/standalone-mode/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/standalone-mode/README.md)
#### 8. 在启用 AppSec 功能的情况下使用 Traefik [examples/appsec-enabled/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/appsec-enabled/README.md)
#### 9. 在启用 Captcha 补救功能的情况下使用 Traefik [examples/captcha/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/captcha/README.md)
#### 10. 在自定义封禁 HTML 页面的情况下使用 Traefik [examples/custom-ban-page/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/custom-ban-page/README.md)
#### 11. 在自定义 Captcha Whiketkeeper 的情况下使用 Traefik [examples/custom-captcha/README.md](https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin/blob/main/examples/custom-captcha/README.md)
### 本地模式
Traefik 还提供了一种开发人员模式,可用于临时测试未托管在 GitHub 上的插件。
要在本地模式下使用插件,Traefik 静态配置必须定义模块名称(这是 Go 包的常规做法)以及指向 [Go 工作区](https://golang.org/doc/gopath_code.html#Workspaces)的路径,该工作区可以是本地 GOPATH 或任何目录。
插件必须放置在 `./plugins-local` 目录中,
该目录应位于运行 Traefik 二进制文件的进程的工作目录中。
插件的源代码应按如下方式组织:
```
./plugins-local/
└── src
└── github.com
└── maxlerebourg
└── crowdsec-bouncer-traefik-plugin
├── bouncer.go
├── bouncer_test.go
├── go.mod
├── LICENSE
├── Makefile
├── readme.md
└── vendor/*
```
对于本地开发,提供了一个 `docker-compose.local.yml`,它重现了 Traefik 所需的目录布局。
一旦您生成并填充了您的 _LAPI-KEY_ (crowdsecLapiKey),此方法即可生效;如果没有,请阅读上方的信息说明。
```
docker compose -f docker-compose.local.yml up -d
```
相当于
```
make run_local
```
### 关于
[mathieuHa](https://github.com/mathieuHa) 和 [我](https://github.com/maxlerebourg) 自 2020 年起就在 [Primadviz](https://primadviz.com) 使用 Traefik。
我们拥有 Web 开发和安全工程师背景,希望将一项极具前景的技术(Crowdsec)的强大功能加入到我们喜爱的边缘路由器中。
我们最初接触到了这个项目:[github.com/fbonalair/traefik-crowdsec-bouncer](https://github.com/fbonalair/traefik-crowdsec-bouncer)
它使用 traefik 和 forward auth 中间件来验证每个请求。
它们必须通过一个 Web 服务器,然后该服务器联系另一个 Web 服务(即 crowdsec LAPI),根据源 IP 做出决策。
我们最初通过实现流模式和本地缓存提出了一些改进。
借着 Traefik 黑客马拉松的机会,我们决定将我们的解决方案直接作为 Traefik 插件实现,这样每个人都可以在 [plugins.traefik.io](https://plugins.traefik.io) 上找到它,并且性能更高。
none 模式工作流
``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant CrowdsecLAPI TraefikPlugin-->>CrowdsecLAPI: Does the User IP has a Crowdsec Decision ? destroy CrowdsecLAPI CrowdsecLAPI-->>TraefikPlugin: Yes a ban Decision TraefikPlugin->>User: No, HTTP 403 ``` ``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant CrowdsecLAPI TraefikPlugin-->>CrowdsecLAPI: Does the User IP has a crowdsec decision ? destroy CrowdsecLAPI CrowdsecLAPI-->>TraefikPlugin: Nothing, all good! destroy TraefikPlugin TraefikPlugin->>Webserver: Forwarding this HTTP Request from User Webserver->>User: HTTP Response ```live 模式工作流
``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant PluginCache TraefikPlugin-->>PluginCache: Does the User IP has a crowdsec decision ? PluginCache-->>TraefikPlugin: Nothing, all good! create participant CrowdsecLAPI TraefikPlugin-->>CrowdsecLAPI: Does the User IP has a crowdsec decision ? destroy CrowdsecLAPI CrowdsecLAPI-->>TraefikPlugin: Yes a ban Decision TraefikPlugin-->>PluginCache: Store the information for this IP for DefaultDecisionSeconds destroy PluginCache PluginCache-->>TraefikPlugin: Done TraefikPlugin->>User: No, HTTP 403 ``` ``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant PluginCache TraefikPlugin-->>PluginCache: Does the User IP has a crowdsec decision ? PluginCache-->>TraefikPlugin: Nothing, all good! create participant CrowdsecLAPI TraefikPlugin-->>CrowdsecLAPI: Does the User IP has a crowdsec decision ? destroy CrowdsecLAPI CrowdsecLAPI-->>TraefikPlugin: Nothing, all good! TraefikPlugin-->>PluginCache: Store the information for this IP for DefaultDecisionSeconds destroy PluginCache PluginCache-->>TraefikPlugin: Done TraefikPlugin->>Webserver: Forwarding this HTTP Request from User Webserver->>User: HTTP Response ```stream 模式工作流
``` sequenceDiagram participant TraefikPlugin participant CrowdsecLAPI TraefikPlugin->>CrowdsecLAPI: What are the current decisions destroy CrowdsecLAPI CrowdsecLAPI->>TraefikPlugin: Here is the list create participant PluginCache TraefikPlugin-->>PluginCache: Store this list destroy PluginCache PluginCache-->>TraefikPlugin: Done ``` ``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant PluginCache TraefikPlugin-->>PluginCache: Does the User IP has a crowdsec decision ? destroy PluginCache PluginCache-->>TraefikPlugin: Yes a ban decision destroy TraefikPlugin TraefikPlugin->>User: No, HTTP 403 ``` ``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant PluginCache TraefikPlugin-->>PluginCache: Does the User IP has a crowdsec decision ? destroy PluginCache PluginCache-->>TraefikPlugin: Nothing, all good! destroy TraefikPlugin TraefikPlugin->>Webserver: Forwarding this HTTP Request from User Webserver->>User: HTTP Response ```alone 模式工作流
``` sequenceDiagram participant TraefikPlugin participant CrowdsecCAPI TraefikPlugin->>CrowdsecCAPI: What are the current decisions from CAPI destroy CrowdsecCAPI CrowdsecCAPI->>TraefikPlugin: Here is the list create participant PluginCache TraefikPlugin-->>PluginCache: Store this list destroy PluginCache PluginCache-->>TraefikPlugin: Done ``` ``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant PluginCache TraefikPlugin-->>PluginCache: Does the User IP has a crowdsec decision ? destroy PluginCache PluginCache-->>TraefikPlugin: Yes a ban decision destroy TraefikPlugin TraefikPlugin->>User: No, HTTP 403 ``` ``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant PluginCache TraefikPlugin-->>PluginCache: Does the User IP has a crowdsec decision ? destroy PluginCache PluginCache-->>TraefikPlugin: Nothing, all good! destroy TraefikPlugin TraefikPlugin->>Webserver: Forwarding this HTTP Request from User Webserver->>User: HTTP Response ```appsec 模式工作流
``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant CrowdsecAppSec TraefikPlugin-->>CrowdsecAppSec: Is this request malicious ? destroy CrowdsecAppSec CrowdsecAppSec-->>TraefikPlugin: Yes I think so destroy TraefikPlugin TraefikPlugin->>User: No, HTTP 403 ``` ``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant CrowdsecAppSec TraefikPlugin-->>CrowdsecAppSec: Is this request malicious ? destroy CrowdsecAppSec CrowdsecAppSec-->>TraefikPlugin: No I don't think so destroy TraefikPlugin TraefikPlugin->>Webserver: Forwarding this HTTP Request from User Webserver->>User: HTTP Response ```Captcha 决策工作流
``` sequenceDiagram participant User participant TraefikPlugin User->>TraefikPlugin: Can I access that webpage create participant PluginCache TraefikPlugin-->>PluginCache: Does the User IP has a Crowdsec Decision ? PluginCache-->>TraefikPlugin: Yes a Catpcha Decision TraefikPlugin->>User: Please complete this captcha User->>TraefikPlugin: Fine, done! create participant ProviderCaptcha TraefikPlugin-->>ProviderCaptcha: Is the validation OK ? destroy ProviderCaptcha ProviderCaptcha-->>TraefikPlugin: Yes TraefikPlugin-->>PluginCache: Set the User IP Clean for captchaGracePeriodSeconds destroy PluginCache PluginCache-->>TraefikPlugin: Done destroy TraefikPlugin TraefikPlugin->>Webserver: Forwarding this HTTP Request from User Webserver->>User: HTTP Response ```标签:AppImage, CISA项目, CrowdSec, EVTX分析, Go语言, IP封锁, Traefik插件, Web应用防火墙, 安全防护, 搜索引擎查询, 日志审计, 程序破解, 网络信息收集, 请求拦截