--- title: Netbis Sigmatch — VL 기반 자동 공격 탐지 + CF 차단 updated: 2026-04-24 tags: [netbis, security, ai-defense, wip] --- ## 개요 Netbis NPM 로그(VictoriaLogs)를 실시간 분석해 **사람 개입 없이 공격을 자동 탐지**하고 CF IP Access Rules에 challenge/block 반영. LAPI·CrowdSec·LLM·사전 정의 룰 모두 사용 안 함. - **저장소**: https://gitea.inouter.com/kaffa/netbis-sigmatch - **로컬 개발**: `~/netbis-sigmatch/` (Mac) - **배포 예정**: jp1 Incus `ai-sigmatch` 컨테이너 (systemd timer 1분) - **책임자**: kappa 직접 개발 (Heimdall 위임 X, 개발 단계) ## 핵심 설계 (v2, 2026-04-24 재설계) ### 탐지 트리거 2종만 **A. 집계 기반 공격 모드** (DDoS 검출) ``` 현재 5분 총 req > baseline_시간대(UTC hour).p95 × 2.0 OR > baseline_시간대.max × 1.5 → attack mode ON → top N contributor IP challenge ``` **B. 개별 극단 (항상 동작)** ``` Scanner-shape: uniq_paths/reqs ≥ 0.8 AND path_entropy ≥ 7 AND reqs ≥ 300 (수백 경로를 각 1회씩 = 취약점 스캐너) Raw extreme: reqs ≥ 1500 / 5min (폴링 유저 상한의 약 7배) ``` ### 롤링 baseline (자동 갱신) - 매 사이클 현재 윈도우 샘플을 `baseline_samples`에 누적 - 시간대(hour_utc)별 p95/max를 최근 7일 롤링 기준으로 실시간 계산 - **공격 판정된 윈도우 샘플은 baseline에 안 들어감** (baseline 오염 방지) - 매 60 사이클마다 7일 초과 샘플 자동 prune - 초기 seed는 `baseline_aggregate.py`로 1회 수집, 롤링 12+ 샘플 쌓이면 seed 대체 ### 폐기된 이전 설계 - ~~IsolationForest + DBSCAN per-IP anomaly~~ → 정상 폴링 유저를 outlier로 잡아 오탐 위험 - ~~Persistence 단독 트리거~~ → 페이지 오래 열어둔 유저 6 사이클 지속 시 오탐 - ~~사전 정의 hard rule (R1~R6)~~ → 공격 패턴 종속, 자동 시그니처 생성 취지 어긋남 ## 오탐 방지 특성 | 상황 | 동작 | |------|------| | 평상시 정상 트래픽 | 액션 0 (heavy user·폴링 유저 다 통과) | | 평상시 섞인 취약점 스캐너 | 개별 극단 트리거 (확정 공격) | | DDoS·대규모 공격 | attack mode 발동 → top contributor 일괄 challenge | | 가짜 공격 (baseline 경계선) | samples ≥ 10 확보 후에만 판정 (초기 1~2일은 판정 유예) | **사람이 쓴 공격 지식 없음**: - 특정 경로·ASN·UA 리스트 없음 - scanner-shape는 행동 통계 (uniq_paths/reqs 비율, entropy) - attack mode는 트래픽 볼륨 이상 — 자기 과거와의 편차만 봄 ## 조치 레벨 - **challenge** (Cloudflare managed_challenge, CAPTCHA, TTL 30분): 정상 유저는 한 번 풀고 통과 - **block** (TTL 24시간): challenge 통과 후에도 같은 IP가 5+ 사이클 연속 공격 시 ## 개발 단계 - [x] Phase 1: feature 추출 (`fetch_features.py`) - [x] Phase 2: 24h retrospective baseline (`collect_baseline.py`) - [x] Phase 3-5: (폐기) IsolationForest+DBSCAN+persistence 기반 - [x] **Phase 6 (v2): 집계 기반 공격 모드 + 개별 극단 시그니처** ← 현재 - [x] **Phase 7: 롤링 baseline 자동 갱신** ← 현재 - [ ] Phase 8: 장시간 관찰 (dry-run) — 진행 중 (백그라운드 `loop.py`) - [ ] Phase 9: CF IP Access Rules 호출 (managed_challenge → block) - [ ] Phase 10: jp1 Incus 배포 (systemd timer) ## 파라미터 (사람 조정 가능) | 파라미터 | 기본값 | 의미 | |---------|-------|------| | `attack_p95_multiplier` | 2.0 | 현재 req가 시간대 p95의 몇 배면 attack mode | | `attack_max_multiplier` | 1.5 | 또는 max의 몇 배면 | | `attack_top_n` | 20 | attack 시 challenge할 상위 IP 수 | | `attack_contributor_min_reqs` | 200 | top IP 중 이 이상인 것만 | | `scanner_uniq_ratio` | 0.8 | uniq_paths/reqs 임계 | | `scanner_min_entropy` | 7.0 | path entropy 임계 | | `scanner_min_reqs` | 300 | 스캐너 최소 요청 수 | | `extreme_reqs` | 1500 | 단일 IP 극단 rate 임계 | | `persistence_for_block` | 5 | challenge → block 승급 사이클 | | `challenge_ttl_sec` | 1800 | 30분 | | `block_ttl_sec` | 86400 | 24시간 | | `baseline_rolling_days` | 7 | 롤링 윈도우 | | `min_baseline_samples` | 10 | baseline 샘플 부족 시 판정 유예 | ## 파일 구조 ``` ~/netbis-sigmatch/ ├── fetch_features.py — feature 추출 (단발 조회) ├── collect_baseline.py — retrospective seed baseline 수집 ├── baseline_aggregate.py — 시간대별 seed 통계 수집 (1회성) ├── inspect_baseline.py — baseline DB 탐색 ├── state.py — state DB (ip_state, baseline_samples 등) ├── loop.py — 메인 실시간 루프 ├── simulate.py — 과거 데이터로 로직 검증 ├── baseline.db — seed snapshot 24h ├── state.db — 운영 상태 + 롤링 baseline └── logs/ — 사이클 로그 ``` ## 연관 정본 - [[../services/netbis]] — NPM → VL 파이프라인 - [[../infra/security/cloudflare#Pseudo IPv4 (Class E 240/4)]] — 240/4 대역 해석 - [[../history/2026-04-24-cf-pseudo-ipv4-discovery]] — CF Pseudo IPv4 규명