Initial commit: CrowdSec BunnyCDN bouncer

- sync/bouncer.py: CrowdSec LAPI → bloom filter → BunnyCDN Edge Script
- edge/middleware.ts: BunnyCDN edge middleware with bloom filter + Turnstile CAPTCHA
- README.md: architecture and deployment docs
This commit is contained in:
kappa
2026-03-15 13:13:54 +09:00
parent 06af81c198
commit 1dcf2f448e
4 changed files with 855 additions and 68 deletions

167
README.md
View File

@@ -1,101 +1,132 @@
# CrowdSec Bunny Bouncer
# CrowdSec BunnyCDN Bouncer
[CrowdSec](https://crowdsec.net) bouncer for [Bunny CDN](https://bunny.net). CrowdSec의 차단 목록을 Bunny CDN Edge Script와 연동하여 악성 IP를 CDN 엣지에서 차단합니다.
CrowdSec LAPI에서 탐지한 악성 IP를 BunnyCDN 에지에서 선제 차단하는 bouncer.
## Architecture
## 아키텍처
```
CrowdSec LAPI ──stream──▶ bouncer.py ──libSQL──▶ Bunny Database
Edge Script (index.ts)
onOriginRequest 에서
DB 조회 → 403 / pass
[CrowdSec LAPI (jp1, 10.253.100.240:8080)]
↓ 크론잡 (3분 간격)
↓ /v1/decisions/stream API
[bouncer.py]
→ IP 목록 → Bloom filter 생성
→ BunnyCDN Compute API로 Edge Script 코드 업데이트
[BunnyCDN Edge Script (middleware.ts)]
→ X-Real-Ip 헤더에서 클라이언트 IP 추출
→ Bloom filter로 IP 매칭
→ 매칭되면 Turnstile CAPTCHA 챌린지
→ 캡차 통과하면 4시간 검증 (verified_ips DB)
→ Bloom filter에 없으면 오리진으로 통과
```
- **bouncer.py** — CrowdSec LAPI Streaming API를 폴링하여 차단 결정을 Bunny Database(libSQL HTTP API)에 동기화
- **edge-script/index.ts** — Bunny CDN Edge Script 미들웨어. 모든 요청에 대해 DB를 조회하고 차단 IP면 403 응답
- **setup.py** — Edge Script 코드를 Bunny CDN에 업로드 및 퍼블리시
- **monitor.py** — Edge Script 사용량, CDN 트래픽/에러, WAF 이벤트 로그 모니터링
## 구성 요소
## Features
### sync/bouncer.py
- CrowdSec Streaming API 기반 실시간 동기화 (기본 60초 간격)
- CAPI(Community Blocklist) 포함 27,000+ IP 처리
- Edge Script 인메모리 캐시 (정상 IP 5분, 차단 IP 1분 TTL)
- Fail-open 설계 — DB 장애 시 요청 허용
- 6시간 주기 전체 재동기화
- 헬스체크 파일 기반 컨테이너 모니터링
CrowdSec LAPI → BunnyCDN Edge Script 동기화 스크립트.
## Prerequisites
- CrowdSec LAPI stream endpoint에서 ban 결정 fetch
- IP 목록을 bloom filter (FNV-1a 해시)로 변환
- BunnyCDN Compute API로 Edge Script 코드 내 `BLOOM_B64` 상수 교체
- 스크립트 퍼블리시
- CrowdSec LAPI 접속 가능 (bouncer API 키 필요)
- Bunny CDN 계정 + Pull Zone
- Bunny Database (libSQL)
- Bunny Edge Scripting 활성화
- Python 3.12+
- Docker/Podman (운영 환경)
### edge/middleware.ts
## Quick Start
BunnyCDN Edge Script 미들웨어 (현재 inouter 풀존에 배포됨, script ID: 64811).
### 1. Bunny Database 및 Edge Script 준비
- `@bunny.net/edgescript-sdk` 사용
- Bloom filter 기반 IP 차단
- Cloudflare Turnstile CAPTCHA로 false positive 대응
- LibSQL DB로 verified IP 4시간 캐싱
- HMAC 서명 쿠키로 세션 유지
- Clean IP 캐시 (네거티브 캐시, 최대 50K)
Bunny 대시보드에서:
1. Database 생성 → URL과 Token 기록
2. Edge Scripting에서 스크립트 생성 → Script ID 기록
3. Edge Script에 `BUNNY_DATABASE_URL`, `BUNNY_DATABASE_AUTH_TOKEN` 환경변수 설정
4. Edge Script를 Pull Zone에 연결
## 환경 변수
### 2. 환경변수 설정
### bouncer.py
| 변수 | 설명 | 기본값 |
|------|------|--------|
| `CROWDSEC_LAPI_URL` | CrowdSec LAPI URL | `http://10.253.100.240:8080` |
| `CROWDSEC_BOUNCER_KEY` | Bouncer API key | (required) |
| `BUNNY_API_KEY` | BunnyCDN account API key | (required) |
| `BUNNY_SCRIPT_ID` | Edge Script ID | `64811` |
| `STATE_FILE` | 상태 파일 경로 | `/var/lib/crowdsec-bouncer/state.json` |
### Edge Script Variables
| 변수 | 설명 |
|------|------|
| `TURNSTILE_SITE_KEY` | Cloudflare Turnstile site key |
| `TURNSTILE_SECRET_KEY` | Cloudflare Turnstile secret key |
| `CACHE_MODE` | 캐시 모드 (auto) |
| `BUNNY_DATABASE_URL` | LibSQL database URL |
| `BUNNY_DATABASE_AUTH_TOKEN` | LibSQL auth token |
## 배포
### 1. CrowdSec bouncer 등록
```bash
cp .env.example .env
# .env 파일 편집
# jp1 crowdsec 컨테이너에서
cscli bouncers add bunny-cdn-bouncer
# 출력된 API key를 Vault에 저장
```
| 변수 | 필수 | 설명 |
|------|------|------|
| `CROWDSEC_LAPI_URL` | O | CrowdSec LAPI 주소 |
| `CROWDSEC_LAPI_KEY` | O | Bouncer API 키 |
| `BUNNY_DB_URL` | O | Bunny Database libSQL URL |
| `BUNNY_DB_TOKEN` | O | Bunny Database 인증 토큰 |
| `SYNC_INTERVAL` | | 동기화 간격 초 (기본: 60) |
| `INCLUDE_CAPI` | | CAPI 차단 목록 포함 (기본: true) |
| `FULL_RESYNC_INTERVAL` | | 전체 재동기화 간격 초 (기본: 21600) |
| `LOG_LEVEL` | | 로그 레벨 (기본: INFO) |
| `BUNNY_API_KEY` | | Bunny API 키 (setup.py, monitor.py용) |
| `BUNNY_SCRIPT_ID` | | Edge Script ID (setup.py용) |
### 3. Edge Script 배포
### 2. Vault에 시크릿 저장
```bash
python setup.py
vault kv put secret/infra/crowdsec-bunny-bouncer \
bouncer_key=<CROWDSEC_BOUNCER_KEY>
```
### 4. Bouncer 실행
### 3. Incus 컨테이너에 배포
```bash
# Docker/Podman
podman compose up -d
# 또는 직접 실행
pip install -r requirements.txt
python bouncer.py
# jp1 infra-tool 컨테이너
pip3 install -r sync/requirements.txt
cp sync/bouncer.py /opt/crowdsec-bouncer/bouncer.py
```
## Monitoring
### 4. Cron 설정
```bash
# 기본 (최근 30일)
python monitor.py
# 기간 지정
python monitor.py 7
# /etc/cron.d/crowdsec-bunny-bouncer
*/3 * * * * root CROWDSEC_BOUNCER_KEY="..." BUNNY_API_KEY="..." /usr/bin/python3 /opt/crowdsec-bouncer/bouncer.py >> /var/log/crowdsec-bouncer.log 2>&1
# 매시 정각: 전체 동기화 (startup mode)
3 * * * * root CROWDSEC_BOUNCER_KEY="..." BUNNY_API_KEY="..." /usr/bin/python3 /opt/crowdsec-bouncer/bouncer.py --startup >> /var/log/crowdsec-bouncer.log 2>&1
```
출력 항목:
- **Edge Script 사용량** — 월간 요청 수, CPU 시간, 무료 한도(25M) 대비 비율
- **CDN 통계** — 총 요청, 캐시 히트율, 대역폭, 3xx/4xx/5xx 에러
- **WAF / Bunny Shield** — Shield 상태, WAF 룰 현황, 이벤트 로그 요약 (공격 유형, IP, 국가별)
## 테스트
```bash
# 테스트 IP 추가
ssh incus-jp1 "incus exec crowdsec -- cscli decisions add -i 198.51.100.1 -d 10m -R 'test'"
# 동기화 실행
python3 sync/bouncer.py --startup -v
# 테스트 IP 제거
ssh incus-jp1 "incus exec crowdsec -- cscli decisions delete -i 198.51.100.1"
python3 sync/bouncer.py -v
```
## 풀존 적용 현황
| 풀존 | ID | 미들웨어 | 상태 |
|------|-----|---------|------|
| inouter | 5316471 | 64811 | 적용됨 |
| actions | 5330178 | - | 미적용 |
## Bloom Filter 세부
- 해시 함수: FNV-1a (32-bit) double hashing
- False positive rate: 0.1%
- 헤더: 8 bytes (m: uint32 LE, k: uint32 LE)
- 페이로드: bit array
- 버전: MD5 해시 앞 16자 (변경 감지용)
## Edge Script Pricing