diff --git a/history/2026-04-23-netbis-bouncer-removal.md b/history/2026-04-23-netbis-bouncer-removal.md new file mode 100644 index 0000000..32646e2 --- /dev/null +++ b/history/2026-04-23-netbis-bouncer-removal.md @@ -0,0 +1,113 @@ +--- +date: 2026-04-23 +topic: Netbis CF 바운서 전량 제거 +areas: [infra/security/crowdsec-safeline.md, services/netbis.md, infra/security/cloudflare.md] +tags: [crowdsec, cloudflare, netbis, removal, cost-control] +--- + +## 배경 + +같은 날 [[2026-04-23-netbis-firewall-bouncer-migration|Firewall Rule 바운서 병행 도입]] 직후 재평가 → **두 바운서 모두 제거 결정**. + +### 재평가 핵심 + +- **Worker Bouncer (`netbis-cf`)**: KV.get 구조. 2026-04 청구서 $100 중 82%가 KV read 오버. Worker 실행 자체가 과금 유발 +- **Firewall Rule Bouncer (`netbis-cf-firewall`)**: CF Rule List 용량 10,000 (Pro). LAPI 전체 decision ~29k 중 67% 초과분은 CF에 동기화 불가. 우선순위 선별이지만 실제 공격자 IP 누락 가능성 + CF API rate limit(10040) 만성 +- **결론**: 두 방식 모두 현재 Netbis 트래픽 규모와 비용 모델에 적합하지 않음. 더 적절한 방어 수단 재설계 필요 (후속 과제) + +## 제거 범위 + +### netbis-cf-firewall (Firewall Rule Bouncer) + +| 리소스 | 상태 | +|---|---| +| systemd service `crowdsec-cloudflare-bouncer.service` | disable + stop | +| 패키지 `crowdsec-cloudflare-bouncer` (0.3.0) | apt purge | +| LAPI bouncer 엔트리 `netbis-cf-firewall` | `cscli bouncers delete` | +| CF Rule List `crowdsec_block` (id `b14745a3306a4f81b46d96593135f78b`, 10,000 items) | DELETE | +| CF Firewall Rules (6 zones) + companion filters | 각 zone DELETE | +| CF scoped API token `crowdsec-cloudflare-bouncer-netbis` (id `2196850b050493d01e0ab9ec0cde3e15`) | DELETE | +| Vault `secret/cloud/cloudflare-netbis` `api_token` 필드 | kappa 경유 제거 예정 | + +### netbis-cf (Worker Bouncer) + +| 리소스 | 상태 | +|---|---| +| systemd service `crowdsec-cloudflare-worker-bouncer.service` | disable + stop | +| 패키지 `crowdsec-cloudflare-worker-bouncer` (0.0.14) | apt purge | +| LAPI bouncer 엔트리 `netbis-cf` | `cscli bouncers delete` | +| CF Worker Script `crowdsec-cloudflare-worker-bouncer` | DELETE | +| CF KV Namespace `CROWDSECCFBOUNCERNS` (id `8cb07c1cb7784a4ca533f319bf66aa64`) | DELETE | +| CF Worker Routes (6 zones, pattern `*/*`) | 각 zone DELETE | +| CF Turnstile widgets (6개 `crowdsec-cloudflare-worker-bouncer-widget`) | DELETE | +| CF User API Token `crowdsec-cf-bouncer-netbis` (`cfut_239XYQ...cf7c816`, id `d06694e98a2e58bfe9e0c338711b3aba`) | DELETE | + +### 컨테이너 자체 + +| 리소스 | 상태 | +|---|---| +| jp1 Incus 컨테이너 `netbis-cf-bouncer` (10.253.103.33) | `incus delete --force` | +| OpenTofu 정의 | 탐색 결과 없음 (heimdall `~/kaffa/ops-agents-tofu/`, kappa Mac 모두 미발견). destroy 대상 없음 | + +### 6개 보호 zone (변경 영향) + +fall-vip.com, fall-mvp.com, fall-vip7.com, psd777.com, rss-555.com, rss-7790.com — CrowdSec 기반 CF 엣지 차단 일시 해제. 다른 계층(SafeLine WAF, BunnyCDN middleware 등)이 있다면 그쪽은 무변경. + +## 실행 순서 + +``` +1. systemctl disable --now crowdsec-cloudflare-bouncer crowdsec-cloudflare-worker-bouncer (jp1:netbis-cf-bouncer) +2. cscli bouncers delete netbis-cf-firewall netbis-cf (jp1:crowdsec) +3. apt purge crowdsec-cloudflare-bouncer crowdsec-cloudflare-worker-bouncer (jp1:netbis-cf-bouncer) +4. CF API (cfut token): Worker Routes × 6 DELETE → Worker Script DELETE → KV Namespace DELETE → Turnstile widgets × 6 DELETE +5. CF API (global_api_key): Firewall Rules × 6 DELETE + Filters × 6 DELETE → IP List DELETE → scoped api_token DELETE → cfut User Token DELETE +6. 컨테이너 내부 잔존 config 백업·log shred → /etc/crowdsec 삭제 → systemctl reset-failed +7. incus delete --force jp1:netbis-cf-bouncer +8. tmux → kappa: Vault api_token 필드 제거 요청 (global_api_key/email/account_id 보존) +``` + +## 검증 + +제거 후 CF 상태 (global_api_key X-Auth 조회): + +| 지표 | 값 | +|---|---| +| Netbis Workers Scripts | 0 | +| Netbis KV Namespaces | 0 | +| 6 zones Worker Routes | 0 각각 | +| 6 zones CrowdSec firewall rules | 0 각각 | +| `crowdsec*` IP Lists | 0 | +| `bouncer*` Turnstile widgets | 0 | +| scoped api_token verify | Invalid API Token | +| cfut User Token verify | Invalid API Token | + +LAPI (jp1:crowdsec): + +``` +cscli bouncers list # netbis-cf, netbis-cf-firewall 둘 다 없음 +``` + +Incus (jp1): + +``` +incus list --all-projects jp1: | grep netbis # (empty) +``` + +## 롤백 불가 영역 + +- 제거된 API 토큰 2개: 값 복구 불가. 필요시 global_api_key로 재발급 +- 삭제된 IP List의 10,000 IP 항목: 재생성 시 LAPI에서 다시 sync (바운서 재설치 필요) +- 삭제된 Turnstile widgets: secret key 포함 완전 파기. 재설치 시 새 widget/secret 발급 +- Worker Script/KV: 재배포로 재생성 가능 + +## 후속 과제 + +- [ ] **Vault `secret/cloud/cloudflare-netbis`의 `api_token` 필드 제거** — kappa 경유 (다른 필드 보존) +- [ ] Netbis 방어 수단 재설계: CF 비용 + 차단 범위 트레이드오프 분석 후 대체 구조 결정 (예: BunnyCDN Edge + SafeLine WAF 조합, CrowdSec → CF Account Rule Lists 단독, CF Custom Ruleset 등) +- [ ] 2026-05 CF 청구서에서 Netbis 요금 감소 확인 (Worker 호출 0 + KV read 0 예상) + +## 관련 문서 + +- [[../infra/security/crowdsec-safeline|crowdsec-safeline]] (섹션 2개 제거됨) +- [[2026-04-23-netbis-firewall-bouncer-migration|이전 history: Firewall Bouncer 도입]] (같은 날, 역전) +- [[../services/netbis|netbis]] (방어 구조 재설계 대상) diff --git a/infra/security/crowdsec-safeline.md b/infra/security/crowdsec-safeline.md index 50a5644..f29e511 100644 --- a/infra/security/crowdsec-safeline.md +++ b/infra/security/crowdsec-safeline.md @@ -221,70 +221,7 @@ cat updated-config.yaml | ssh incus-jp1 "incus file push - cs-cf-worker-bouncer/ ssh incus-jp1 "incus exec cs-cf-worker-bouncer -- systemctl restart crowdsec-cloudflare-worker-bouncer" ``` -### netbis-cf (Cloudflare Worker — Netbis 계정) - -Kappa 계정용 `cs-cf-worker-bouncer`와 별도 컨테이너로 분리 운영. 상세: [[netbis]] - -| 항목 | 값 | -|------|-----| -| 위치 | jp1 Incus `netbis-cf-bouncer` 컨테이너 (10.253.103.33) | -| 바운서 이름 | netbis-cf | -| 설정 | `/etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml` | -| 동기화 | 10초 | -| CF 계정 | Netbis (netbis@netbis.io, Account ID 8fcf3c7876332aba33e974cbbfdad951) | -| 보호 zone | fall-vip.com, fall-mvp.com, fall-vip7.com, psd777.com, rss-555.com, rss-7790.com | -| Turnstile | 6개 zone managed 모드, 168시간 secret key 로테이션 | -| 로그 소스 | sandbox-tokyo APISIX → CrowdSec http-logger (8085/apisix-logs) | - -### netbis-cf-firewall (Cloudflare Firewall Rule — Netbis 계정, 비용 방어) - -`netbis-cf` Worker Bouncer와 **병행** 운영. Worker Bouncer는 Worker 실행 후 KV.get 구조라 KV read 비용이 그대로 청구됨 (2026-04 청구서 $100 중 82%가 KV read 오버). Firewall Rule 바우언서는 CF 엣지 단계에서 IP를 차단 — Worker가 실행되지 않아 Worker/KV 비용 0. Worker Bouncer는 Turnstile/정교한 챌린지용으로 계속 사용. - -| 항목 | 값 | -|------|-----| -| 위치 | jp1 Incus `netbis-cf-bouncer` 컨테이너 (10.253.103.33, Worker Bouncer와 동일 컨테이너) | -| 패키지 | `crowdsec-cloudflare-bouncer` v0.3.0 (crowdsec apt repo) | -| 바운서 이름 | `netbis-cf-firewall` (cscli 등록) | -| 설정 | `/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml` (mode 600) | -| 동기화 | LAPI 10초, CF 업데이트 30초 | -| CF 계정 | Netbis (netbis@netbis.io, Account ID 8fcf3c7876332aba33e974cbbfdad951) | -| CF 인증 | scoped API token `crowdsec-cloudflare-bouncer-netbis` (Vault `secret/cloud/cloudflare-netbis` `api_token` 필드). 권한: Account Rule Lists Write + Account Settings Read + Zone Firewall Services Write + Zone WAF Write + Zone Read (All zones of account). 발급 주체: global_api_key 경유 CF API | -| IP List | `crowdsec` (CF Rule Lists, account scope) — ip_list_prefix 설정 | -| IP List 용량 | 10000 (Free/Pro 공통 상한, `total_ip_list_capacity`) | -| 보호 zone | fall-vip.com, fall-mvp.com, fall-vip7.com, psd777.com, rss-555.com, rss-7790.com (6) | -| Action | `block` (단일) — 모든 zone, default_action 동일 | -| Firewall Rule | 각 zone 당 1건 (6건 자동 생성, `ip.src in $crowdsec` 조건) | -| 로그 | `/var/log/crowdsec-cloudflare-bouncer.log` (log_mode: file) | - -### 바우언서 역할 분담 (Netbis) - -``` -LAPI (jp1 crowdsec) → 두 바우언서 병행 구독 - ├─ netbis-cf (Worker Bouncer) → CF Worker + KV (정교한 차단·captcha·Turnstile) - └─ netbis-cf-firewall (FW Bouncer) → CF Rule List + Firewall Rule (엣지 즉시 차단, Worker 실행 없음) -``` - -Firewall Rule이 먼저 평가되어 차단되면 Worker는 아예 실행되지 않아 KV 비용 미발생. Worker까지 도달한 요청에 대해서만 captcha/Turnstile 플로우 적용. - -### 운영 주의 - -- IP 용량 초과 시 바우언서 로그에 `N IPs won't be inserted/kept to avoid exceeding IP list limit` 경고. LAPI 전체 decision 수가 10000 초과면 일부 IP는 CF에 반영 안 됨 (바우언서가 우선순위로 선별) -- CF Rule Lists items API는 레이트리밋 존재 (에러 10040). 바우언서는 자동 재시도로 다음 사이클에서 처리 -- scoped API token 권한 부족으로 CF Rulesets API 403 발생 시 `Account Rulesets:Edit` 추가 후 재발급 필요 - -### 적용 / 재기동 - -```bash -# config 전체 푸시 (sed -i 금지) -cat updated-config.yaml | ssh incus-jp1 'incus exec netbis-cf-bouncer -- tee /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml >/dev/null' -ssh incus-jp1 'incus exec netbis-cf-bouncer -- systemctl restart crowdsec-cloudflare-bouncer' - -# 상태 -ssh incus-jp1 'incus exec netbis-cf-bouncer -- systemctl status crowdsec-cloudflare-bouncer' -ssh incus-jp1 'incus exec netbis-cf-bouncer -- tail -f /var/log/crowdsec-cloudflare-bouncer.log' -``` - -도입 이력: [[../../history/2026-04-23-netbis-firewall-bouncer-migration|history]] +> **Netbis CF 바운서 전량 제거 (2026-04-23)** — Worker Bouncer (`netbis-cf`) + Firewall Rule Bouncer (`netbis-cf-firewall`) 모두 폐기. Worker/KV 비용 구조 + CF IP List 10k 한도의 이중 한계로 두 방식 모두 비용 대비 효과 불충분 판단. 컨테이너·패키지·LAPI 엔트리·CF 리소스(Worker/KV/Routes/Turnstile/Rule List/Firewall Rules)·API 토큰 모두 삭제. 상세: [[../../history/2026-04-23-netbis-bouncer-removal|history]] ### bunny-cdn-bouncer (BunnyCDN Edge Script)