Files
obsidian/infra/security/crowdsec-safeline.md
kaffa 03ef787444 cf-bouncer: fall-mvp.com zone 제거 — netbis CF bouncer 21일 만에 동기화 재개
fall-mvp.com zone이 CF에서 삭제되어 bouncer가 2026-05-02부터 fatal 루프로 정지. config에서 2줄 제거 후 enable+start. LAPI pull 2026-05-23T04:56:28Z로 갱신 확인.
- infra/security/crowdsec-safeline.md: 적용 zone 6 → 5
- history/2026-05-23-cf-bouncer-fall-mvp-removal.md: 인시던트 기록
2026-05-23 14:00:25 +09:00

23 KiB
Raw Permalink Blame History

title, updated
title updated
CrowdSec 및 SafeLine WAF 2026-04-25

CrowdSec LAPI

항목
위치 jp1 Incus crowdsec 컨테이너
LAPI http://10.253.100.240:8080
관리 ssh incus-jp1 "incus exec crowdsec -- cscli ..."
버전 v1.7.7 (최신, 2026-04-17 확인)

로그 수집 (Acquisition)

Traefik → CrowdSec (Vector)

Traefik DaemonSet (stdout JSON accessLog)
  → Vector Agent DaemonSet (K3s logging ns, kubernetes_logs source)
  → VRL transform (access log만 필터, non-JSON abort)
  → HTTP sink (배치 50건, 5초)
  → CrowdSec HTTP acquisition (:8086/traefik-logs)
  → crowdsecurity/traefik-logs 파서
항목
Vector Helm vector/vector 0.51.0, Agent DaemonSet (3노드)
Values ~/k8s/vector/values.yaml
CrowdSec 포트 8086
인증 Authorization: traefik-crowdsec-log-2024
파서 crowdsecurity/nginx-logs (Hub, 표준 nginx combined). Vector에서 모든 로그를 표준 포맷으로 변환 후 VictoriaLogs 저장

APISIX + Traefik + NPM → VictoriaLogs → CrowdSec (통합 acquisition, 2026-04-25)

서울 APISIX (K3s) stdout → Vector DaemonSet ─┐
오사카 APISIX (Docker) stdout → Vector ────────┤
K3s Traefik stdout → Vector DaemonSet ────────┤→ VictoriaLogs (ES bulk API)
Netbis NPM 6대 nginx file → Vector → zlambda─┘
                                             ↓
  CrowdSec victorialogs acquisition (tail, 실시간, 단일 query OR로 통합)
  → custom/apisix-json-logs 파서 + crowdsecurity/nginx-logs (NPM 호환)

[!note] anomaly-detect 분기 제거 (2026-04-25) 기존 + anomaly-detect (5분 폴링, AI 분석) 분기는 폐기. ../platform/anomaly-detect 인스턴스 완전 제거. ../../history/2026-04-25-anomaly-detect-removal

항목
VictoriaLogs vl.inouter.com (K3s logging ns, Traefik IngressRoute)
통합 acquisition /etc/crowdsec/acquis.d/victorialogs-nginx.yaml (source: victorialogs, query: (program:apisix AND log_type:access) OR program:traefik OR (program:npm AND log_type:access), labels: type: nginx)
이전 분리 파일 victorialogs-apisix.yaml.bak, victorialogs-traefik.yaml.bak, victorialogs-npm-netbis.yaml.bak (롤백용 보존)
서울 Vector K3s DaemonSet (Helm vector/vector), parse_apisix / parse_traefik transform → vlogs ES sink
오사카 Vector Docker timberio/vector:0.45.0-debian, parse_apisixvlogs. location: osaka 필드 추가
Netbis NPM 경로 NPM 호스트 Vector → zlambda vector-relay → VL npm-netbis 인덱스. nginx-logs parser가 NPM proxy format 호환 (cscli explain 검증)
파서 crowdsecurity/nginx-logs (Vector가 표준 nginx combined로 변환). NPM은 raw proxy format도 grok으로 핵심 필드 추출 정상

APISIX → log-collector → CrowdSec (sandbox-tokyo)

sandbox-tokyo APISIX http-logger
  → log-collector (jp1 crowdsec 컨테이너, :8087)
  → SQLite (/var/lib/log-collector/requests.db)
  → CrowdSec HTTP acquisition (:8085/apisix-logs) 포워딩
항목
log-collector Go HTTP 서버, /usr/local/bin/log-collector (jp1 crowdsec 컨테이너)
소스 jp1 ~/log-collector/main.go
수신 포트 8087
인증 Authorization: apisix-crowdsec-log-2024
SQLite /var/lib/log-collector/requests.db
기능 APISIX 로그 수신 → SQLite 저장 → CrowdSec 포워딩, 타임스탬프 밀리초 보정

Netbis NPM → zlambda → VictoriaLogs (6대 오리진, 2026-04-23 수집 / 2026-04-25 CrowdSec 연동)

NPM-1..6 (Linode Tokyo public) Vector 0.55 file→http
  → zlambda(Tailscale+public) Vector-relay 0.45 http_server→elasticsearch
  → vl.inouter.com (index `npm-netbis`)
  → CrowdSec victorialogs acquisition (위 통합 파일에 query OR로 합류, 2026-04-25 연동)
  → nginx-logs parser → 시나리오 매칭 → LAPI decision (origin: crowdsec)

Netbis 오리진(NPM) nginx access/error 로그 수집. VL 은 LAN-only(192.168.9.53) 이므로 public NPM이 도달할 수 없어 zlambda 를 HTTP 중계로 투입. 상세: ../../services/netbis#로그-수집-vector-→-zlambda-→-victorialogs, ../../history/2026-04-23-netbis-npm-vl-collection

2026-04-25 CrowdSec 연동 완료. 통합 acquisition /etc/crowdsec/acquis.d/victorialogs-nginx.yaml 의 query에 (program:npm AND log_type:access) 추가. : 초기 cscli explain 결과로 "nginx-logs parser가 NPM proxy format도 lenient 호환"이라 적었던 부분은 잘못된 검증이었음 — 실제로는 child-crowdsec/nginx-logs unparsed 84%로 grok 미매칭. 정정 사항은 아래 _msg 재합성 서브섹션 참조.

_msg 재합성 (proxy_v2 → nginx combined, 2026-04-25)

CrowdSec crowdsecurity/nginx-logs Hub 파서는 표준 NGINXACCESS grok 만 매칭한다. NPM 의 proxy_v2 raw 포맷([Client x] [Real y] ...)은 grok 미지원이라 child-crowdsec/nginx-logs unparsed 84% 발생. 해결: NPM Vector remap에 _msg 재작성 블록 추가 — 이미 추출된 메타필드(client_ip/method/path/status/bytes/user_agent/referer/log_time)로 표준 nginx combined 포맷을 합성해 .message 에 덮어쓰기. 원본은 .original_message 에 보존. 검증: cscli explain --type nginx 결과 s01-parse: crowdsecurity/nginx-logs (+23 ~2) 통과 + 시나리오(crowdsecurity/http-crawl-non_statics, custom/apisix-high-rate-per-ip, custom/apisix-single-path-flood) 매칭 확인. 상세: ../../history/2026-04-25-netbis-npm-vector-msg-rewrite

_msg 가 이제 표준 nginx combined 포맷이라 hub 파서 그대로 동작 — 통합 acquisition의 (program:npm AND log_type:access) 분기에서 LAPI decision까지 자연스럽게 흐름.

SafeLine → CrowdSec (실시간, PG LISTEN/NOTIFY)

SafeLine WAF 차단 → mgt_detect_log_basic INSERT
  → PG 트리거 (notify_detect_log) → pg_notify('safeline_detect', JSON)
  → safeline-listener (kr2, Go) → detail 테이블 enrichment (x-real-ip, user-agent)
  → CrowdSec HTTP acquisition (:8088/safeline-logs)
  → custom/safeline-http-logs 파서
  → custom/safeline-waf-blocked 시나리오 (trigger, 즉시 밴)
항목
safeline-listener Go, /usr/local/bin/safeline-listener (kr2)
소스 kr2 ~/safeline-listener/main.go
systemd safeline-listener.service (kr2)
PG DSN SafeLine CE DB (10.43.8.243:5432, safeline-ce)
CrowdSec 포트 8088
인증 Authorization: safeline-crowdsec-2026
acquis 설정 /etc/crowdsec/acquis.d/safeline-http.yaml
파서 custom/safeline-http-logs (/etc/crowdsec/parsers/s01-parse/safeline-http-logs.yaml)
시나리오 custom/safeline-waf-blocked (trigger 타입, 즉시 밴)
enrichment req_header에서 x-real-ip, user-agent 추출, detail 테이블에서 method/payload 조회

PG 트리거 (SafeLine CE DB에 설치):

CREATE OR REPLACE FUNCTION notify_detect_log() RETURNS trigger AS $$
BEGIN
  PERFORM pg_notify('safeline_detect', json_build_object(
    'id', NEW.id, 'ts', NEW.created_at,
    'src_ip', NEW.src_ip, 'host', NEW.host,
    'url_path', NEW.url_path, 'attack_type', NEW.attack_type
  )::text);
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_detect_log
  AFTER INSERT ON mgt_detect_log_basic
  FOR EACH ROW EXECUTE FUNCTION notify_detect_log();

ddos-detect (AI 행위 분석) — 폐기 (2026-04-08)

[!warning] 폐기됨 2026-04-08 분석기 서비스 정지 + 삭제. "이 방식으로는 안 될 것 같다"는 판단 (60초 폴링 + Claude CLI 동기 호출 구조의 한계). 새로운 AI 분석 아키텍처는 victorialogs 기반으로 재설계 예정.

제거된 항목: ddos-detect.service (systemd), /var/lib/log-collector/ddos-detect/ Go 바이너리 + 소스, ddos-detect.sh, extract_behavior.py, ddos-logs/ (분석 결과 markdown). requests.db는 별개의 log-collector 데몬이 사용 중이라 보존. Gitea repo kaffa/ddos-detect는 보존 (코드 reference).

이전 동작 (참고):

항목
위치 jp1 crowdsec 컨테이너 /var/lib/log-collector/ddos-detect/
Gitea gitea.inouter.com/kaffa/ddos-detect
기능 SQLite 폴링 → IP별 행위 패턴 추출 → Claude AI 분석 → cscli 자동 밴
설정 config.yaml (poll 60s, Claude sonnet, ban 4h, max_workers 3)

리얼 IP 처리

경로 설정 source IP 추출
BunnyCDN → HAProxy → Traefik forwardedHeaders.trustedIPs: 127/8, 10/8, 172.16/12, 192.168/16 + externalTrafficPolicy: Local ClientHost (X-Forwarded-For에서 추출)
BunnyCDN → HAProxy → APISIX real_ip_header: X-Forwarded-For + real_ip_from: 127/8, 10.42/16, 10.43/16, 192.168.9/24, 100.64/10 client_ip (nginx real_ip 모듈)

Traefik values: ~/k8s/traefik/values.yaml

시나리오

유형 시나리오 출처
HTTP http-probing, http-crawl-non_statics, http-sensitive-files, http-backdoors-attempts, http-sqli-probing, http-xss-probing 등 Hub
SafeLine custom/safeline-waf-blocked (trigger), custom/safeline-waf-repeated (3+/5min) 로컬
APISIX (2026-04-08 신규) custom/apisix-high-rate-per-ip, custom/apisix-499-burst, custom/apisix-single-path-flood, custom/apisix-5xx-burst 로컬
CAPI http:dos, http:scan, ssh:bruteforce (커뮤니티) 자동

APISIX 시나리오 (4종, 2026-04-08 작성)

ddos-detect AI 분석기 폐기 후 deterministic 패턴 매칭으로 대체. 모두 leaky bucket, ban 4h. K3s 서울 APISIX 트래픽만 보고 판단 (osaka/zlambda는 http-logger 송신 안 함).

시나리오 매개변수 의도 filter
apisix-high-rate-per-ip capacity 1000, leakspeed 100ms (≈ sustained 10 req/s, burst 1000) 일반 HTTP flood. APISIX 자체 limit-req(20 req/s)에 안 걸리는 sustained 패턴 log_type=http_access-log, groupby source_ip
apisix-499-burst capacity 30, leakspeed 2s connection exhaustion / Slowloris (클라이언트 강제 끊김) http_status == "499"
apisix-single-path-flood capacity 50, leakspeed 600ms 동일 path 반복 (CAPTCHA 우회, login bf, 동일 자원 폭격) groupby source_ip + ":" + http_path
apisix-5xx-burst capacity 20, leakspeed 3s 백엔드 부하 유발성 공격, 취약점 스캔 http_status startsWith "5"

⚠️ 운영 주의:

  • 5xx-burst: 백엔드 장애 시 false positive 가능. 운영 알람과 분리해서 검토.
  • 499-burst: 모바일 클라이언트 끊김으로 정상 발생할 수 있어 30 임계값을 며칠 관찰 후 조정 권장.
  • 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):

"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.

발견 사항: K3s APISIX 글로벌 limit-req

{
  "key_type": "var",
  "key": "remote_addr",
  "rate": 20,
  "burst": 10,
  "rejected_code": 429
}

/apisix/global_rules/limit-req (etcd). 모든 라우트에 적용. CrowdSec 시나리오는 이 1차 차단을 통과한 트래픽만 본다는 점을 고려해서 임계값 설계.

Bouncer

[!note] Bouncer 단일화 (2026-04-26) CrowdSec bouncer를 netbis-cf-firewall 단일로 통합. 아래 strikethrough 항목 3종 (cs-cf-worker-bouncer / apisix-waf-bouncer / bunny-cdn-bouncer) 모두 폐기. 사유: 운영 단순화 + 비용 구조 비효율 + Worker bouncer Turnstile 위젯 168h rotation 부담. SafeLine WAF / APISIX limit-req / netbis-cf-firewall 보호는 그대로 유지.

사라진 enforce 영역: kappa zone(keepanker.cv, actions.it.com, ironclad.it.com, servidor.it.com) CrowdSec ban / BunnyCDN 풀존(iron-jp, iron-kr) 엣지 차단 / APISIX 인스턴스 chaitin-waf 보완용 IP ban.

상세: ../../history/2026-04-26-bouncer-consolidation

cs-cf-worker-bouncer (Cloudflare Worker) — 폐기 (2026-04-26)

../../history/2026-04-26-bouncer-consolidation 참조. jp1 incus cs-cf-worker-bouncer 컨테이너 + 설정 파일 + LAPI 등록 모두 제거. CF Worker 스크립트 / KV namespace / Turnstile 위젯 4개 (crowdsec-cloudflare-worker-bouncer-widget)는 Syn에 위임 정리.

Netbis CF 바운서 (2026-04-23 폐기 → 2026-04-25 Firewall Rule 단독 재구축)

2026-04-23: Worker + Firewall Rule 두 종류 모두 폐기 (Worker/KV 비용 + CF IP List 10k 한도). ../../history/2026-04-23-netbis-bouncer-removal

2026-04-25: netbis-cf-firewall 만 재구축. 폐기 사유였던 10k 한도는 origin filter [crowdsec, cscli] 적용으로 회피 (CAPI/lists 30k+ 무시, 로컬 시나리오 발동만 푸시). Worker bouncer는 트래픽 비례 비용 구조라 origin filter로 회피 불가, 재구축 안 함.

자세한 배경 및 구성: ../../history/2026-04-25-netbis-cf-firewall-rebuild, ../../services/netbis#cloudflare-firewall-bouncer-재구축-2026-04-25

netbis-cf-firewall (Cloudflare Firewall Rule Bouncer, 재구축 2026-04-25)

항목
컨테이너 jp1 incus crowdsec (LAPI와 같은 컨테이너에 동거)
패키지 crowdsec-cloudflare-bouncer 0.3.0 (apt)
동작 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 (모든 5 zone 동일). LAPI decision type 무관하게 CF managed_challenge 액션으로 적용 → 사용자는 CF 캡챠 페이지 통과 후 진입. 분산 DDoS 시나리오 오탐 시에도 ban이 아니라 캡챠
CF 리소스 IP List crowdsec_managed_challenge (f728ad9d4653467396d32466902c9e52), 5 zone × Firewall Rule (managed_challenge 액션) 자동 생성
적용 zone fall-vip / fall-vip7 / psd777 / rss-555 / rss-7790 (Account ID 8fcf3c7876332aba33e974cbbfdad951). 2026-05-23 fall-mvp.com zone이 CF에서 삭제됨에 따라 config에서 제거
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
인증 방식 Bearer (Authorization: Bearer cfut_...). global_api_key는 Invalid request headers (6003)사용 불가 — 신규 token 발급 필수
config /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml
systemd crowdsec-cloudflare-bouncer.service
비용 $0 (Free plan 영역, IP List + Firewall Rule). Worker bouncer 대비 비용 구조 우월
한계 CF 공식 deprecation 표기 ("isn't actively supported anymore"). 동작은 정상이나 향후 호환성 변화 가능

cs-cf-worker-bouncer (kappa 계정용)는 별도 컨테이너에서 그대로 운영2026-04-26 폐기. 현재 LAPI 등록 bouncer는 본 항목(cs-cloudflare-bouncer-1777082222) 단 하나. ../../history/2026-04-26-bouncer-consolidation

bunny-cdn-bouncer (BunnyCDN Edge Script) — 폐기 (2026-04-26)

../../history/2026-04-26-bouncer-consolidation 참조. jp1 infra-tool 컨테이너 cron + /opt/crowdsec-bouncer/bouncer.py 제거. LAPI 등록 삭제. BunnyCDN Edge Script 64811 (crowdsec-bouncer-middleware) 두 풀존(iron-jp 5555247 / iron-kr 5555227) middleware 해제 + 스크립트 삭제는 Syn 위임. Vault secret/infra/crowdsec-bunny-bouncer 시크릿 보존(별도 폐기 결정).

apisix-waf-bouncer (APISIX plugin) — 폐기 (2026-04-26)

apisix-plugin-crowdsec-bouncer 0.1 — APISIX 인스턴스(가능성: apisix-osaka)의 chaitin-waf 보완용 IP ban 플러그인. LAPI 등록 삭제 완료. APISIX plugin 비활성화 + plugin_metadata/route 정리는 Syn 위임. K3s 서울 / zlambda APISIX 는 미사용 확인 완료. 상세: ../../history/2026-04-26-bouncer-consolidation

보안 구조 (2026-04-26 bouncer 단일화 이후)

클라이언트 → BunnyCDN WAF (OWASP CRS, 1차) — 일반 도메인 경로
          → Traefik / APISIX + SafeLine WAF (2차)
          → CrowdSec 로그 분석 (3차) → netbis-cf-firewall (Netbis 5 zone CF Firewall Rule 피드백 루프)

netbis 전용 enforce: CF Account IP List + 5 zone Firewall Rule managed_challenge (netbis-cf-firewall)
일반 zone enforce 사라짐 — kappa zone CrowdSec ban 미적용. BunnyCDN Edge bouncer / Worker bouncer / APISIX bouncer 모두 폐기 (2026-04-26)

1차: BunnyCDN WAF (OWASP CRS)

  • CDN 에지에서 오리진 도달 전 차단
  • 차단: SQLi, XSS, CMDi, SSRF, Shellshock, Log4j
  • 비활성화: DATA LEAKAGES SQL (id=911) — NocoDB 오탐 방지
  • 통과: Request Smuggling, NoSQLi, 경로 스캔

2차: SafeLine WAF (chaitin-waf)

  • APISIX plugin_metadata → detector 10.43.253.244:8000
  • SafeLine v9.3.2, K3s safeline ns
  • 관리: safeline.inouter.com, API 헤더 X-SLCE-API-TOKEN
  • 토큰: Vault secret/infra/safeline
  • tengine 미사용, APISIX 직접 연동

3차: CrowdSec 로그 분석

  • Traefik / APISIX 로그: Vector → VictoriaLogs(vl.inouter.com) → CrowdSec victorialogs acquisition (tail 모드)
  • SafeLine 차단: PG NOTIFY → safeline-listener → CrowdSec HTTP acquisition(:8088)
  • sandbox-tokyo APISIX: http-logger → log-collector(:8087) → CrowdSec
  • HTTP 시나리오 매칭 → decision → bouncer 피드백

iron-kr-waf BunnyCDN Pull Zone (구 waf-kr)

APISIX 외부 인입 경로 (juiceshop SafeLine 통합 테스트 용도). APISIX 자체는 독립 LoadBalancer gateway (MetalLB 192.168.9.50) 이지 "SafeLine 전용" 이 아님 — 현재 1 route 가 SafeLine 용일 뿐.

항목
Zone ID 5555224
Name iron-kr-waf
Origin https://220.120.65.245:9443
경로 인터넷 → BunnyCDN(iron-kr-waf) → OpenWrt HAProxy(:9443) → MetalLB 192.168.9.50:443 → APISIX(K3s 서울) → chaitin-waf → SafeLine detector → K3s svc

등록 호스트: iron-kr-waf.b-cdn.net, juiceshop.keepanker.cv (WAF 테스트용). ApisixRoute juiceshop (chaitin-waf block) → juiceshop:3000.

옛 메모의 waf-kr (5554681) 는 더 이상 존재하지 않음 — iron-kr-waf (5555224) 로 통합·재명명됨.

화이트리스트

파서 대역 이유
crowdsecurity/whitelists (Hub) 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, ::1, 127.0.0.0/8 RFC1918 사설 IP
custom/tailscale-whitelist (로컬) 100.64.0.0/10 Tailscale CGNAT

2026-04-17 추가: 기존에 crowdsecurity/whitelists 파서가 미설치 상태여서 내부 IP(192.168.9.1 OpenWrt)가 반복 밴됨. 설치 후 해결.

Profile (decision 발급)

/etc/crowdsec/profiles.yaml — 시나리오 매칭 시 LAPI에 emit할 decision type을 결정하는 단계.

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 분기 추가 필수 (예시):

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)

항목
타입 HTTP (Discord Bot API)
이름 http_default
채널 Discord #heimdall (1488119168145555486)
트리거 remediation=true인 모든 decision (IP, Range)
그룹 30초 대기, 5건 이상 즉시
Bot 토큰 Vault secret/apps/discordbot_token
설정 /etc/crowdsec/notifications/http.yaml

참고

  • BunnyCDN WAF 차단 시 오리진에 로그 안 옴 → CrowdSec에 미수신
  • OpenWrt CrowdSec firewall bouncer는 DNAT 구조라 리얼 IP 매칭 불가
  • chaitin-waf 플러그인은 plugin_attr이 아닌 **plugin_metadata(etcd)**에서 detector 노드를 읽음
  • Incus 컨테이너에서 sed -i로 설정 수정 시 파일 손상 주의 (전체 파일 push 사용)