Files
obsidian/infra/crowdsec-safeline.md

6.3 KiB

title, updated
title updated
CrowdSec 및 SafeLine WAF 2026-03-28

CrowdSec LAPI

항목
위치 jp1 Incus crowdsec 컨테이너
LAPI http://10.253.100.240:8080
관리 ssh incus-jp1 "incus exec crowdsec -- cscli ..."

로그 수집 (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/traefik-logs (Hub, JSON 모드)

APISIX → CrowdSec (http-logger)

APISIX (global_rules http-logger 플러그인)
  → 배치 50건, 5초 buffer
  → CrowdSec HTTP acquisition (:8085/apisix-logs)
  → custom/apisix-json-logs 파서
항목
설정 APISIX Admin API global_rules/1
CrowdSec 포트 8085
인증 Authorization: apisix-crowdsec-log-2024
파서 custom/apisix-json-logs (로컬)

리얼 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) 로컬
CAPI http:dos, http:scan, ssh:bruteforce (커뮤니티) 자동

Bouncer

cs-cf-worker-bouncer (Cloudflare Worker)

항목
위치 jp1 Incus cs-cf-worker-bouncer 컨테이너
설정 /etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml
정본 gitea.inouter.com/kaffa/k3s-configcrowdsec/crowdsec-cloudflare-worker-bouncer.yaml
동기화 10초 (decision stream polling)
방식 LAPI → bouncer → Cloudflare Worker KV (bloom filter) → Worker에서 차단/captcha
보호 zone keepanker.cv, actions.it.com, ironclad.it.com, inouter.com, servidor.it.com
Turnstile 5개 zone managed 모드, 168시간 secret key 로테이션

Decision 수동 관리

bouncer의 lapi_key읽기 전용. decision 추가/삭제는 crowdsec 컨테이너에서 cscli로:

# ban 추가
ssh incus-jp1 "incus exec crowdsec -- cscli decisions add --ip 1.2.3.4 --duration 2m --reason 'manual ban' --type ban"

# 확인
ssh incus-jp1 "incus exec crowdsec -- cscli decisions list --ip 1.2.3.4"

# 삭제
ssh incus-jp1 "incus exec crowdsec -- cscli decisions delete --ip 1.2.3.4"

bouncer 컨테이너에서 curl POST /v1/decisions로 직접 넣으면 등록 안 됨 — API 키 권한 제한.

설정 변경 시 주의

sed -i 사용 금지 — Incus 컨테이너 내에서 sed -i로 수정 시 이전 내용이 파일 끝에 남아 YAML 깨짐. 반드시 전체 파일 덮어쓰기:

cat updated-config.yaml | ssh incus-jp1 "incus file push - cs-cf-worker-bouncer/etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml"
ssh incus-jp1 "incus exec cs-cf-worker-bouncer -- systemctl restart crowdsec-cloudflare-worker-bouncer"

bunny-cdn-bouncer (BunnyCDN Edge Script)

항목
동기화 jp1 infra-tool 컨테이너, /opt/crowdsec-bouncer/bouncer.py
크론 3분 delta sync, 매시 full sync
방식 LAPI → Bloom filter → BunnyCDN Edge Script 임베딩 → 퍼블리시
Edge Script ID 64811 (crowdsec-bouncer-middleware), FNV-1a bloom filter
차단 시 Cloudflare Turnstile CAPTCHA + LibSQL verified IP 캐싱(4h)
적용 풀존 iron-jp (5555247)
API 키 Vault secret/infra/crowdsec-bunny-bouncer
소스 ~/crowdsec-bunny-bouncer/

보안 구조

클라이언트 → BunnyCDN Edge Script (CrowdSec bouncer, 0차)
          → BunnyCDN WAF (OWASP CRS, 1차)
          → Traefik / APISIX + SafeLine WAF (2차)
          → CrowdSec 로그 분석 (3차) → bouncer 피드백 루프

0차: BunnyCDN Edge Script (CrowdSec bouncer)

  • Bloom filter로 악성 IP 즉시 차단
  • false positive 시 Turnstile CAPTCHA로 구제

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 로그: Vector DaemonSet → :8086crowdsecurity/traefik-logs
  • APISIX 로그: http-logger → :8085custom/apisix-json-logs
  • HTTP 시나리오 매칭 → decision → bouncer 피드백

waf-kr BunnyCDN Pull Zone

APISIX SafeLine WAF 전용.

항목
Zone ID 5554681
Name waf-kr
Origin https://220.120.65.245:9443
경로 인터넷 → BunnyCDN(waf-kr) → HAProxy(:9443) → APISIX(31137) → SafeLine → K3s

등록 호스트: juiceshop.keepanker.cv (WAF 테스트용)

참고

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