crowdsec: profile current state, distributed DDoS scenario notes, bouncer action mapping
- profile.yaml is ban-only — captcha/throttle decision은 emit 안 됨 - Hub 분산 DDoS 시나리오 (http-ddos-by-ASN/cn) 도입 시 profile 분기 필수 - cs-cf-worker-bouncer: default_action captcha (Turnstile) - netbis-cf-firewall: default_action managed_challenge (6 zone) - 두 bouncer 모두 LAPI decision type 무관하게 캡챠 페이지로 응답
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: CrowdSec 및 SafeLine WAF
|
||||
updated: 2026-04-23
|
||||
updated: 2026-04-25
|
||||
---
|
||||
|
||||
## CrowdSec LAPI
|
||||
@@ -181,6 +181,28 @@ ddos-detect AI 분석기 폐기 후 deterministic 패턴 매칭으로 대체.
|
||||
- `high-rate-per-ip`: APISIX `limit-req` 글로벌 룰(20 req/s burst 10)을 통과한 트래픽만 도달 → 1차 통과 후 sustained pattern을 잡는 2차 layer.
|
||||
- 현재 모두 `remediation: true` (즉시 ban). dry-run으로 시작 안 함 — false positive 발생 시 임계값 또는 ban duration 조정.
|
||||
|
||||
### 분산 DDoS 시나리오 (Hub, 도입 검토)
|
||||
|
||||
per-IP 시나리오는 분산(여러 IP 합산) 패턴을 못 잡음. CrowdSec Hub에서 제공하는 공식 시나리오로 보완 가능.
|
||||
|
||||
| 시나리오 | groupby | distinct | capacity | leakspeed | 의도 |
|
||||
|---|---|---|---|---|---|
|
||||
| `crowdsecurity/http-ddos-by-ASN` | `evt.Meta.ASNNumber` | `evt.Meta.source_ip` | 20 | 10s | 동일 ASN에서 distinct IP 20개가 10초 안에 도달 |
|
||||
| `crowdsecurity/http-ddos-by-cn` | `evt.Meta.IsoCode` | `evt.Meta.source_ip` | 50 | 30s | 동일 국가에서 distinct IP 50개가 30초 안에 도달 |
|
||||
|
||||
공식 필터에 false positive 회피책이 미리 깔려 있음:
|
||||
- `http_status == '200'` → 백엔드 5xx 장애 시 자폭 차단
|
||||
- `static_ressource == 'false'` → CDN miss/이미지 burst 제외
|
||||
- `distinct: source_ip` → 단일 IP 반복이 아닌 IP 다양성으로 측정
|
||||
|
||||
CrowdSec 공식 가이드 명시 사항 ([blog](https://www.crowdsec.net/blog/mitigate-ddos-with-crowdsec)):
|
||||
> "banning these given countries will mean false positives and collateral damage."
|
||||
|
||||
→ **분산 시나리오는 ban이 아니라 `captcha` decision으로 emit하라는 게 공식 권장.** Hub 페이지에도 dos 계열은 "proper testing is advised" 경고가 직접 표기됨 (예: `http-dos-bypass-cache`).
|
||||
|
||||
**도입 전 점검 필요 (2026-04-25 현재 상태)**:
|
||||
- profile.yaml은 ban only — captcha decision을 emit하려면 분기 추가 필수 (아래 [#알림-notification] 참조).
|
||||
- bouncer 측 액션 매핑은 이미 captcha 쪽이라 ban으로 emit해도 사용자 체감은 캡챠와 동일 (아래 bouncer 절 표 참조). 하지만 의미 일관성을 위해 profile에 captcha 분기 도입 권장.
|
||||
|
||||
과거 인시던트 및 변경 이력은 `history/` 참조. 예: `history/2026-04-10-edge-cleanup.md` (cf-audit-cleanup-2 3-incident chain, Turnstile sitekey 교체, 미들웨어 64811 `/__captcha/verify` 버그 수정 등), [[2026-04-15-apisix-http-logger-removal|2026-04-15 APISIX http-logger 레거시 제거]].
|
||||
|
||||
@@ -209,6 +231,7 @@ ddos-detect AI 분석기 폐기 후 deterministic 패턴 매칭으로 대체.
|
||||
| 정본 | `gitea.inouter.com/kaffa/k8s` → `configs/crowdsec/crowdsec-cloudflare-worker-bouncer.yaml` |
|
||||
| 동기화 | 10초 (decision stream polling) |
|
||||
| 방식 | LAPI → bouncer → Cloudflare Worker KV (bloom filter) → Worker에서 차단/captcha |
|
||||
| **액션 매핑** | `default_action: captcha` (Turnstile). LAPI decision type이 ban이든 captcha든 모두 Turnstile 페이지로 처리됨 |
|
||||
| 보호 zone | keepanker.cv, actions.it.com, ironclad.it.com, servidor.it.com |
|
||||
| 비보호 zone | inouter.com, anvil.it.com — DNS `proxied: false` 라 CF 엣지를 거치지 않아 bouncer 라우트가 enforce 되지 않음. 보호는 BunnyCDN 미들웨어 64811 단독 |
|
||||
| Turnstile 위젯 | 4개 bouncer-managed (`crowdsec-cloudflare-worker-bouncer-widget` 이름, 168h rotation). BunnyCDN 미들웨어용 `inouter-bunny-middleware` 는 별도 수동 관리 — [[cloudflare#Turnstile 위젯]] |
|
||||
@@ -257,6 +280,7 @@ ssh incus-jp1 "incus exec cs-cf-worker-bouncer -- systemctl restart crowdsec-clo
|
||||
| 동작 | LAPI 폴링(10s) → CF Account IP List + Zone Firewall Rule 갱신 |
|
||||
| LAPI bouncer 이름 | `cs-cloudflare-bouncer-1777082222` (자동 생성, rename 보류) |
|
||||
| **origin filter** | `only_include_decisions_from: [crowdsec, cscli]` (CAPI/lists 30k+ 무시 → CF List 10k 한도 회피) |
|
||||
| **액션 매핑** | `default_action: managed_challenge` (모든 6 zone 동일). LAPI decision type 무관하게 CF managed_challenge 액션으로 적용 → 사용자는 CF 캡챠 페이지 통과 후 진입. 분산 DDoS 시나리오 오탐 시에도 ban이 아니라 캡챠 |
|
||||
| CF 리소스 | IP List `crowdsec_managed_challenge` (`f728ad9d4653467396d32466902c9e52`), 6 zone × Firewall Rule (managed_challenge 액션) 자동 생성 |
|
||||
| 적용 zone | fall-vip / fall-mvp / fall-vip7 / psd777 / rss-555 / rss-7790 (Account ID `8fcf3c7876332aba33e974cbbfdad951`) |
|
||||
| API token | Vault `secret/cloud/cloudflare-netbis` (`firewall_bouncer_token`, `firewall_bouncer_token_id`). 권한: Account Firewall Access Rules Write + Account Rule Lists Write + Zone Firewall Services Write |
|
||||
@@ -337,6 +361,40 @@ APISIX 외부 인입 경로 (juiceshop SafeLine 통합 테스트 용도). APISIX
|
||||
|
||||
2026-04-17 추가: 기존에 `crowdsecurity/whitelists` 파서가 미설치 상태여서 내부 IP(192.168.9.1 OpenWrt)가 반복 밴됨. 설치 후 해결.
|
||||
|
||||
## Profile (decision 발급)
|
||||
|
||||
`/etc/crowdsec/profiles.yaml` — 시나리오 매칭 시 LAPI에 emit할 decision type을 결정하는 단계.
|
||||
|
||||
```yaml
|
||||
name: default_ip_remediation
|
||||
filters: [Alert.Remediation == true && Alert.GetScope() == "Ip"]
|
||||
decisions: [{type: ban, duration: 4h}]
|
||||
notifications: [http_default]
|
||||
on_success: break
|
||||
---
|
||||
name: default_range_remediation
|
||||
filters: [Alert.Remediation == true && Alert.GetScope() == "Range"]
|
||||
decisions: [{type: ban, duration: 4h}]
|
||||
notifications: [http_default]
|
||||
on_success: break
|
||||
```
|
||||
|
||||
**현재 상태: ban-only**. captcha/throttle decision은 emit되지 않음. ASN/Country scope 핸들러도 없음 — 분산 DDoS 시나리오를 import하면 매칭은 되지만 어떤 profile에도 안 잡혀서 decision 자체가 발급 안 될 수 있음 (`on_success: break` 없는 fallthrough 동작 확인 필요).
|
||||
|
||||
분산 DDoS 시나리오 도입 시 **상단에 captcha 분기 추가 필수** (예시):
|
||||
|
||||
```yaml
|
||||
name: distributed_ddos_captcha
|
||||
filters:
|
||||
- Alert.Remediation == true && Alert.GetScenario() matches "(?i)ddos-by-(asn|cn|country|range)"
|
||||
decisions:
|
||||
- type: captcha
|
||||
duration: 1h
|
||||
on_success: break
|
||||
---
|
||||
# 기존 default_ip_remediation, default_range_remediation
|
||||
```
|
||||
|
||||
## 알림 (Notification)
|
||||
|
||||
| 항목 | 값 |
|
||||
@@ -344,11 +402,10 @@ APISIX 외부 인입 경로 (juiceshop SafeLine 통합 테스트 용도). APISIX
|
||||
| 타입 | HTTP (Discord Bot API) |
|
||||
| 이름 | `http_default` |
|
||||
| 채널 | Discord `#heimdall` (1488119168145555486) |
|
||||
| 트리거 | remediation=true인 모든 ban (IP, Range) |
|
||||
| 트리거 | remediation=true인 모든 decision (IP, Range) |
|
||||
| 그룹 | 30초 대기, 5건 이상 즉시 |
|
||||
| Bot 토큰 | Vault `secret/apps/discord` → `bot_token` |
|
||||
| 설정 | `/etc/crowdsec/notifications/http.yaml` |
|
||||
| 프로필 | `/etc/crowdsec/profiles.yaml` — `default_ip_remediation`, `default_range_remediation` |
|
||||
|
||||
## 참고
|
||||
|
||||
|
||||
Reference in New Issue
Block a user