netbis: crowdsec-cloudflare-bouncer (firewall rule) 추가 — worker bouncer와 병행
This commit is contained in:
143
history/2026-04-23-netbis-firewall-bouncer-migration.md
Normal file
143
history/2026-04-23-netbis-firewall-bouncer-migration.md
Normal file
@@ -0,0 +1,143 @@
|
||||
---
|
||||
date: 2026-04-23
|
||||
topic: Netbis Firewall Bouncer 도입 (Worker Bouncer 병행)
|
||||
areas: [infra/security/crowdsec-safeline.md, services/netbis.md, infra/security/cloudflare.md]
|
||||
tags: [crowdsec, cloudflare, bouncer, netbis, cost-control]
|
||||
---
|
||||
|
||||
## 배경
|
||||
|
||||
Netbis 계정 2026-04 Cloudflare Workers 요금 $100 중 **82%가 KV read 비용 오버**. Worker Bouncer(`netbis-cf`) 구조는 요청이 CF에 도달 → Worker 실행 → KV.get으로 IP 확인 → 차단/통과 순서. 즉 Worker가 실행돼야 KV read가 발생. 악성 IP라 결국 차단해도 KV read 비용은 이미 청구됨.
|
||||
|
||||
기존 Bouncer는 제거하지 않고 **병행**. Worker Bouncer는 Turnstile/captcha 등 정교한 챌린지용 유지, Firewall Rule Bouncer는 엣지 즉시 차단으로 Worker 실행 자체를 회피해 비용 방어.
|
||||
|
||||
## 최종 구조
|
||||
|
||||
```
|
||||
LAPI (jp1:crowdsec, 10.253.100.240:8080)
|
||||
├─ netbis-cf → CF Worker + KV (기존, Turnstile/정교)
|
||||
└─ netbis-cf-firewall → CF Rule List + Firewall Rule (신규, 엣지 차단)
|
||||
```
|
||||
|
||||
CF 요청 평가 순서상 Firewall Rule → Worker. Firewall Rule에서 block되면 Worker는 실행되지 않아 KV read 없음.
|
||||
|
||||
## 실행 단계
|
||||
|
||||
### 1. 사전 조사 — CF 플랜 / IP List 용량
|
||||
|
||||
6개 zone 플랜 (scoped API 아님, global_api_key X-Auth 조회):
|
||||
|
||||
| Zone | Zone ID | Plan |
|
||||
|---|---|---|
|
||||
| fall-vip.com | 662312b0ca619d1d5c8f4c112150d749 | Pro |
|
||||
| fall-mvp.com | 6c171579912a271c0fc89c8187493b0f | Free |
|
||||
| fall-vip7.com | a8832b9d3b546f96505abeadea4750d1 | Free |
|
||||
| psd777.com | a14533c2937b19e5b7ed19cbecd58679 | Pro |
|
||||
| rss-555.com | 6d4b084940520c1f820927e5d8ade2c6 | Pro |
|
||||
| rss-7790.com | d9db9e50e202339326498baa340a9d16 | Pro |
|
||||
|
||||
Free/Pro/Biz 공통 IP list 상한 = 10,000. `total_ip_list_capacity: 10000` 설정.
|
||||
|
||||
### 2. 컨테이너 패키지 설치
|
||||
|
||||
`jp1:netbis-cf-bouncer` (기존 Worker Bouncer 컨테이너 재사용, 서비스 분리).
|
||||
|
||||
```bash
|
||||
incus exec jp1:netbis-cf-bouncer -- apt-get update
|
||||
incus exec jp1:netbis-cf-bouncer -- apt-get install -y crowdsec-cloudflare-bouncer # v0.3.0
|
||||
```
|
||||
|
||||
### 3. LAPI 바우언서 등록
|
||||
|
||||
```bash
|
||||
incus exec jp1:crowdsec -- cscli bouncers add netbis-cf-firewall
|
||||
# API key 출력을 즉시 설정 파일에 주입
|
||||
```
|
||||
|
||||
### 4. CF scoped API token 발급
|
||||
|
||||
v0.3.0 바우언서는 `cloudflare.NewWithAPIToken(token)` **Bearer-only**. Global API Key는 X-Auth 헤더 전용이라 `token` 필드에 그대로 못 넣음 (Bearer auth에서 `Invalid request headers` 거절 확인). 해결: global_api_key 경유로 scoped API token 신규 발급.
|
||||
|
||||
| 항목 | 값 |
|
||||
|---|---|
|
||||
| Token 이름 | `crowdsec-cloudflare-bouncer-netbis` |
|
||||
| Account 스코프 | Netbis (8fcf3c7876332aba33e974cbbfdad951) 전용, All zones |
|
||||
| TTL | 무기한 |
|
||||
| 권한 | Account Rule Lists Write + Account Settings Read + Zone Firewall Services Write + Zone WAF Write + Zone Read |
|
||||
| 저장 | Vault `secret/cloud/cloudflare-netbis` `api_token` 필드 (기존 `global_api_key` 보존) |
|
||||
|
||||
발급 시 CF API permission_group IDs:
|
||||
- `2edbf20661fd4661b0fe10e9e12f485c` Account Rule Lists Write
|
||||
- `c1fde68c7bcc44588cbb6ddbc16d6480` Account Settings Read
|
||||
- `43137f8d07884d3198dc0ee77ca6e79b` Firewall Services Write
|
||||
- `fb6778dc191143babbfaa57993f1d275` Zone WAF Write
|
||||
- `c8fed203ed3043cba015a93ad1616f1f` Zone Read
|
||||
|
||||
메모: `Account.Account Filter Lists:Edit` (user 스펙 명)은 현재 CF에서 `Account Rule Lists Write`로 이름 변경됨. 기능 동일. Rulesets API 경로 사용 시 403 발생하면 `Account Rulesets:Edit` (`56907406c3d548ed902070ec4df0e328`) 추가 후 재발급.
|
||||
|
||||
### 5. Config 파일 전송
|
||||
|
||||
`/etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml` — 전체 파일 push (sed -i 금지, Incus 컨테이너 내 in-place 편집 피함):
|
||||
|
||||
```bash
|
||||
incus exec jp1:netbis-cf-bouncer --mode=non-interactive -- \
|
||||
bash -c 'cat > /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml && chmod 600 /etc/crowdsec/bouncers/crowdsec-cloudflare-bouncer.yaml' \
|
||||
< /tmp/crowdsec-cloudflare-bouncer.yaml
|
||||
```
|
||||
|
||||
주요 값:
|
||||
- `crowdsec_lapi_url: http://10.253.100.240:8080`
|
||||
- `crowdsec_lapi_key`: cscli bouncers add 출력
|
||||
- `cloudflare_config.accounts[0].token`: 위에서 발급한 scoped token
|
||||
- `ip_list_prefix: crowdsec`
|
||||
- `default_action: block`, 모든 zone `actions: [block]` 단일
|
||||
- `total_ip_list_capacity: 10000`
|
||||
|
||||
### 6. 서비스 기동 + CF 리소스 자동 생성
|
||||
|
||||
```bash
|
||||
incus exec jp1:netbis-cf-bouncer -- systemctl enable --now crowdsec-cloudflare-bouncer
|
||||
```
|
||||
|
||||
바우언서 부팅 직후:
|
||||
- CF IP List `crowdsec` (ID `b14745a3306a4f81b46d96593135f78b`) 생성 — Account Rule List
|
||||
- 6개 zone에 firewall rule 자동 생성 (ip.src in $crowdsec → block)
|
||||
- LAPI 스트림 첫 풀: 28,885건 decision 수신, 10,000건 CF로 push
|
||||
|
||||
### 7. E2E 검증
|
||||
|
||||
- 추가 경로: `cscli decisions add --ip 203.0.113.99 --duration 2m --type ban` → LAPI 기록 확인 → 바우언서 다음 사이클에 처리. **단 LAPI 총량 > 10k 상황에서 신규 IP는 용량 우선순위 밀려 CF 반영 보장 안 됨**. 실제 테스트에서 `1 IPs won't be inserted/kept to avoid exceeding IP list limit` 경고 발생
|
||||
- 삭제 경로: CF 리스트 내 IP (`1.14.7.100`) LAPI decision 삭제 → 다음 사이클 제거. CF API 레이트리밋(10040) 영향으로 즉시 반영 아닌 다음 rate-limit window 이후 반영
|
||||
- 실제 push 성공 증거: 바우언서 로그 `added 10000 new IPs and deleted 0 IPs` — 초기 sync 정상
|
||||
|
||||
### 8. Obsidian 커밋 + graphify
|
||||
|
||||
- `infra/security/crowdsec-safeline.md` — `### netbis-cf-firewall` 서브섹션 추가, 바우언서 역할 분담 도식
|
||||
- `history/2026-04-23-netbis-firewall-bouncer-migration.md` — 이 문서
|
||||
- commit: `netbis: crowdsec-cloudflare-bouncer (firewall rule) 추가 — worker bouncer와 병행`
|
||||
- `/graphify update ~/obsidian`
|
||||
|
||||
## 운영 관찰 사항
|
||||
|
||||
### IP List 용량 제약
|
||||
|
||||
LAPI 전체 decision 수가 ~29k, CF Pro 제한 10k. 바우언서는 10k 초과분을 우선순위 선별해 push하지 않음. 결과:
|
||||
- **오래된/높은 우선순위 decision은 CF 반영** (일관성 있는 차단)
|
||||
- **신규 short-TTL decision은 CF 반영 불확실** (커뮤니티 CAPI 결정 다수 + 큰 TTL 누적 영향)
|
||||
- 운영상 Worker Bouncer 경로가 여전히 필요한 이유 — Firewall Rule로 못 잡는 부분은 Worker Bouncer가 KV 조회로 커버
|
||||
|
||||
### CF API 레이트리밋 (10040)
|
||||
|
||||
바우언서 `update_frequency: 30s`에서 매 사이클 신규 IP 1~수건 push 시도. CF Rule List items API 제한(분당 N건)에 금방 도달. 로그에 `you have been ratelimited` 출력, 다음 사이클에서 자동 재시도.
|
||||
|
||||
### 향후 개선 후보
|
||||
|
||||
- CrowdSec LAPI `only_include_decisions_from` 필터로 CAPI 커뮤니티 feed 제외 → 차단 quality 향상하고 CF 10k 용량 효율화
|
||||
- `include_scenarios_containing: ["http"]` 등 시나리오 필터로 포커스
|
||||
- Enterprise zone 업그레이드 시 `total_ip_list_capacity: 50000` 가능
|
||||
|
||||
## 영향 및 롤백
|
||||
|
||||
- Worker Bouncer `netbis-cf` 무변경 — 병행 운영, 기존 Turnstile/captcha 동작 그대로
|
||||
- 롤백: `systemctl stop crowdsec-cloudflare-bouncer && cscli bouncers delete netbis-cf-firewall` + CF IP List/Firewall Rule 수동 삭제 (Rule List `crowdsec` + 6 zone firewall rules)
|
||||
- CF 요금 방어 효과는 다음 월 청구서에서 확인 가능
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: CrowdSec 및 SafeLine WAF
|
||||
updated: 2026-04-17
|
||||
updated: 2026-04-23
|
||||
---
|
||||
|
||||
## CrowdSec LAPI
|
||||
@@ -236,6 +236,56 @@ Kappa 계정용 `cs-cf-worker-bouncer`와 별도 컨테이너로 분리 운영.
|
||||
| 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]]
|
||||
|
||||
### bunny-cdn-bouncer (BunnyCDN Edge Script)
|
||||
|
||||
| 항목 | 값 |
|
||||
|
||||
Reference in New Issue
Block a user