ironclad 트래픽 흐름을 명시: - CF + BunnyCDN 병행 entry (zone proxied 패턴별 분기) - OpenWrt 라우터 (192.168.9.1) → MetalLB → K3s APISIX + SafeLine - 1차 limit-req + 2차 chaitin-waf in-line gRPC - 로그: VL → CrowdSec acquisition → 자작 4종 + hub 시나리오 - enforce layer: CF/BunnyCDN bouncer 모두 폐기 후 재구축 미정 · CF bouncer: netbis-cf-firewall과 동일 패턴으로 kappa account용 추가 운영 후보 · BunnyCDN bouncer: BlockedIps API 또는 Shield Access List(Advanced) — Ticket 388529 답변 후 결정 자산 매핑 표를 netbis/ironclad/bridge로 분리해 명시 추적 시 주의 항목 보강
13 KiB
13 KiB
title, updated, tags
| title | updated | tags | ||||||
|---|---|---|---|---|---|---|---|---|
| 도메인 경계 — netbis vs ironclad (cross-domain 운영) | 2026-04-27 ironclad 자체 cycle 추가 (CF + BunnyCDN 병행, OpenWrt → K3s APISIX+SafeLine, enforce layer 재구축 미정) |
|
도메인 경계와 cross-domain 운영
ironclad 자체 인프라가 netbis의 보안 운영을 위탁받아 처리하는 구조. 두 영역의 자산/계정은 별개지만, 데이터는 netbis에서 발생 → ironclad가 처리 → 결정은 netbis CF에 다시 적용되는 cyclic cross-domain 패턴.
이 정본은 그 경계와 흐름을 한 자리에 정리해서 다른 정본들이 흩어져 갖고 있는 책임/계정 정보의 단일 진입점 역할을 한다.
두 영역의 자산
| 영역 | CF account | 인프라 자산 | 책임 |
|---|---|---|---|
| netbis | netbis CF account (별도, ID 8fcf3c7876332aba33e974cbbfdad951) |
netbis CF zone 6개 (fall-vip / fall-mvp / fall-vip7 / psd777 / rss-555 / rss-7790) + NPM-1..6 (Linode Tokyo public 6대 호스트) |
사용자 트래픽 종착점 (origin) — 외부 노출 도메인은 netbis 자산 |
| ironclad | kappa CF account (kappa@inouter.com) |
jp1/kr1/kr2/hp2 incus, K3s 서울/오사카, vl.inouter.com (VL), CrowdSec LAPI (jp1), netbis-cf-firewall, kappa CF zone (keepanker.cv / actions.it.com / ironclad.it.com / servidor.it.com / inouter.com / anvil.it.com 등) |
인프라 본체 + 분석 layer + 자체 워크로드 (Outline / Gitea / Vault / 등) |
| zlambda | (중립) | NixOS Tokyo 호스트, Tailscale + Linode public IP 둘 다 보유 | 양 영역의 다리 — VL이 LAN-only(192.168.9.53)라 public NPM이 도달 못 함. HTTP relay로 투입 |
데이터 흐름 1 — netbis cycle (cross-domain cyclic)
[사용자 요청]
│
▼
[netbis CF zone (netbis 영역)]
- netbis CF account의 6 zone (fall-vip 등)
- netbis-cf-firewall이 IP List `crowdsec_managed_challenge` + Firewall Rule 적용
- hit IP는 managed_challenge (CF 캡챠), miss는 통과
│
▼ (CF 통과)
[NPM-1..6 origin (netbis 영역, Linode Tokyo public)]
- nginx-proxy-manager proxy_v2 포맷 access log 기록
- 응답을 사용자에 전달
│
│ access log (Vector 0.55 file→http)
▼
[zlambda Vector-relay (다리)]
- Vector 0.45 http_server→elasticsearch
- .relay = "zlambda" 태그 추가
│
▼ (HTTP relay)
[vl.inouter.com (ironclad 영역, K3s logging ns)]
- VictoriaLogs `npm-netbis` 인덱스에 적재
- K3s 클러스터 LAN-only 자산
│
▼ (CrowdSec acquisition tail query)
[CrowdSec LAPI (ironclad 영역, jp1 incus crowdsec 컨테이너)]
- victorialogs source가 query OR로 NPM/APISIX/Traefik 통합 입수
- NPM 라인은 Vector remap이 nginx combined 포맷으로 재합성한 _msg를 대상으로 grok
- 시나리오 매칭 → LAPI decision (origin: crowdsec, scope: Ip)
│
▼ (cscli decisions stream polling, 10s)
[netbis-cf-firewall (ironclad 영역, jp1 crowdsec 컨테이너에 동거)]
- 같은 컨테이너에 LAPI + bouncer 동거지만 bouncer는 netbis CF API token으로 동작
- origin filter `[crowdsec, cscli]` 적용 — CAPI/lists 30k+ 무시 (CF List 10k 한도 회피)
│
▼ (Cloudflare API: netbis CF account)
[netbis CF IP List + Firewall Rule (netbis 영역)]
- IP List `crowdsec_managed_challenge` 갱신
- 6 zone × Firewall Rule managed_challenge 액션 자동 동기화
│
▲ (다음 요청에 반영)
[사용자 요청 ← 차단/캡챠]
데이터 흐름 2 — ironclad cycle (자체 워크로드)
netbis와 달리 ironclad는 CDN을 CF + BunnyCDN 병행으로 운영한다. 두 엣지가 동일한 origin(K3s 서울 클러스터)으로 수렴하고, 분석/결정/enforce는 모두 ironclad 인프라 내부 cycle.
[사용자 요청]
│
├──────────────┬──────────────┐
▼ ▼ │
[Cloudflare] [BunnyCDN 풀존] │ 병행 — proxied 패턴 별로 분기
(proxy=on) (iron-kr/iron-jp) │
kappa zone inouter.com 등 │
│ │ │
│ ※ enforce layer 현재 상태:
│ - CF bouncer (cs-cf-worker-bouncer) → 폐기 2026-04-26
│ - BunnyCDN bouncer (Edge Script 64811) → 폐기 2026-04-26
│ - 양쪽 모두 IP-list 기반 enforce 부재 (재구축 미완)
│
└──────┬───────┘
▼
[OpenWrt 라우터 (kr1 LAN, 192.168.9.1)]
- HAProxy frontend (KR 진입점)
- TCP 로드밸런싱 → MetalLB L2 (192.168.9.50/51) → K3s
│
▼ (MetalLB LB → K3s svc)
[K3s 서울 — APISIX (서울 ns) + SafeLine WAF (safeline ns)]
- 인입: APISIX가 ApisixRoute / Gateway API 처리
- WAF: APISIX `chaitin-waf` plugin이 SafeLine detector를 in-line gRPC 호출 (10.43.253.244:8000)
- 1차 차단 layer: APISIX 글로벌 limit-req (rate 20, burst 10)
- 2차 차단 layer: SafeLine WAF (OWASP CRS + 커스텀 룰)
- origin 워크로드 (Outline / Gitea / Vault / 기타) 호출
│
│ access log (Vector DaemonSet)
▼
[vl.inouter.com (K3s logging ns)]
- APISIX/Traefik/SafeLine 로그 적재
- netbis NPM 로그와 같은 VL이지만 다른 인덱스/program 라벨
│
▼ (CrowdSec acquisition tail query, 통합 query OR)
[CrowdSec LAPI (jp1 incus crowdsec 컨테이너)]
- 시나리오: hub HTTP CVE 시나리오 + 자작 APISIX 4종 (high-rate-per-ip / 499-burst / single-path-flood / 5xx-burst) + safeline-waf-blocked
- 시나리오 매칭 → LAPI decision (origin: crowdsec)
│
├──────────────┬──────────────┐
▼ ▼ │
[CF bouncer] [BunnyCDN bouncer] │ enforce 분기 (양쪽 모두 재구축 필요)
(재구축 미정) (재구축 미정) │
│ │ │
▼ ▼ │
[kappa CF zone] [BunnyCDN 풀존] │
enforce enforce │
│
▲ (다음 요청에 반영)
[사용자 요청 ← 차단]
enforce layer 재구축 계획 (미정 / 진행 중)
| 분기 | 현재 상태 | 후보 |
|---|---|---|
| Cloudflare (kappa CF zone) | bouncer 부재 | netbis-cf-firewall과 같은 패턴(crowdsec-cloudflare-bouncer apt 패키지)으로 별도 인스턴스 또는 동일 인스턴스에 kappa CF token 추가 운영 |
| BunnyCDN (iron-kr/iron-jp 등) | bouncer 부재 | Pull Zone BlockedIps 배열 push 또는 Shield Access List (Advanced 플랜) — 한도/방식은 BunnyCDN 지원 Ticket 388529 답변 후 결정 |
| OpenWrt 라우터 | DNAT 통과 layer (decision enforce 안 함) | 검토 필요 — DNAT 구조라 IP 기반 차단 적용 가능 여부 별건 |
자산 → 도메인 매핑 (주요 노드)
netbis 자산
| 노드 / 자산 | 비고 |
|---|---|
netbis CF account (8fcf3c…) |
별도 계정 |
netbis CF zone × 6 (fall-vip / fall-mvp / fall-vip7 / psd777 / rss-555 / rss-7790) |
사용자 노출 도메인 |
| NPM-1..6 (Linode Tokyo public) | nginx-proxy-manager origin 6대 |
ironclad 자산
| 노드 / 자산 | 비고 |
|---|---|
kappa CF account (d8e5997e…) |
ironclad 자체 운영 |
kappa CF zone (proxied=on: keepanker.cv / actions.it.com / ironclad.it.com / servidor.it.com) |
CF 엣지 진입 |
kappa CF zone (proxied=off: inouter.com / anvil.it.com) |
CF 엣지 미경유 — BunnyCDN 단독 |
BunnyCDN 풀존 (iron-kr 5555227 / iron-jp 5555247 / iron-kr-waf 5555224 / iron-git 5584382 등) |
BunnyCDN 엣지 진입 |
OpenWrt 라우터 (kr1 LAN 192.168.9.1) |
KR 진입점 + HAProxy TCP LB |
MetalLB L2 (192.168.9.50/51 등) |
OpenWrt → K3s svc bridge |
| K3s 서울 (4노드 클러스터) | 메인 워크로드 클러스터 |
K3s apisix ns (서울 APISIX) |
인그레스 게이트웨이 |
K3s safeline ns (SafeLine detector 10.43.253.244:8000) |
WAF 처리 (chaitin-waf in-line gRPC) |
| K3s 워크로드 ns (Outline / Gitea / Vault / n8n / 등) | 사용자 호출 종착점 |
vl.inouter.com (K3s logging ns) |
LAN-only, public 도달 불가 |
jp1 incus crowdsec 컨테이너 |
LAPI + netbis-cf-firewall 동거 |
bridge 자산
| 노드 / 자산 | 비고 |
|---|---|
zlambda (NixOS Tokyo, 139.162.71.52 + Tailscale 100.108.39.107) |
Vector relay 전용. netbis NPM → ironclad VL 도달용 다리 |
Vault secret/cloud/cloudflare-netbis |
netbis CF API token. ironclad Vault에 저장하지만 netbis 권한만 보유 |
netbis-cf-firewall (cs-cloudflare-bouncer-1777082222) |
jp1 ironclad 컨테이너에 동거하지만 netbis CF에 push (ironclad 인프라가 netbis 운영 위탁) |
cross-domain 운영 패턴
패턴 1: 데이터 위탁 (netbis → ironclad)
netbis가 NPM 로그를 ironclad VL로 보낸다. 이유:
- netbis는 자체 로그 분석 인프라 없음
- ironclad가 CrowdSec/VictoriaLogs/시나리오 운영 노하우 보유
- public NPM → LAN VL 도달 불가 → zlambda relay 필수
패턴 2: 결정 위탁 (ironclad → netbis CF)
ironclad CrowdSec이 netbis CF에 ban 결정을 push한다. 이유:
- ironclad가 분석 결과 보유 (시나리오 매칭, IP-based decision)
- netbis CF account에 직접 enforce해야 사용자 트래픽 차단 가능
- 별도 CF account 토큰을 ironclad Vault에 저장하고 ironclad 컨테이너에서 사용
패턴 3: 동거 (jp1 crowdsec 컨테이너)
한 컨테이너에 ironclad LAPI + netbis 전용 bouncer가 동거. 분리 안 한 이유:
- bouncer가 LAPI를 같은 컨테이너 localhost로 호출 → 네트워크 hop 0
- 각자 다른 CF account 토큰 사용이라 사실상 격리됨
- 단
cscli bouncers list/cscli decisions list같은 운영 시점에는 ironclad 운영자가 netbis bouncer 상태도 같이 본다 (의도된 합쳐진 운영 시점)
권한·시크릿 분리
| 시크릿 | 위치 | 용도 |
|---|---|---|
netbis CF API token (firewall_bouncer_token) |
Vault secret/cloud/cloudflare-netbis |
netbis CF Account Firewall Access Rules Write + Account Rule Lists Write + Zone Firewall Services Write |
| netbis CF zone 자체 관리 토큰 | Vault secret/cloud/cloudflare-netbis |
DNS / zone 설정 (별도) |
| kappa CF API key (kappa account) | Vault secret/cloud/cloudflare |
ironclad zone 전체 (global_api_key 사용) |
| zlambda Vector relay basic auth | Vault secret/cloud/vector-relay-netbis |
NPM-1..6 → zlambda HTTP 인증 |
netbis CF token은 ironclad 인프라가 netbis CF에 푸시하기 위한 위탁 권한이지 ironclad 자산 token 아님. 운영자(kappa)가 양쪽 자산 모두 관리하지만, 토큰 자체는 영역별로 분리.
추적 시 주의 (graphify / LLM 추론용)
- CrowdSec 시나리오 매칭은 ironclad VL 데이터 위에서 일어남. netbis IP가 어떤 zone을 노렸는지는 VL
npm-netbis인덱스 host/path 필드 backward query 필요. ironclad 자체 트래픽은 program별(apisix/traefik) 라벨로 분리됨 - netbis-cf-firewall이 push하는 IP List는 netbis CF account에만 적용 — kappa CF zone에는 영향 없음
- kappa zone과 BunnyCDN 풀존은 IP-list 기반 enforce layer 부재 (2026-04-26 cs-cf-worker-bouncer + bunny-cdn-bouncer 폐기 후 재구축 미완) — CrowdSec 결정이 발급되어도 ironclad 트래픽 entry 단계에서 enforce되지 못함. SafeLine WAF / APISIX limit-req는 in-cluster에서 작동 (1차/2차 layer 유지)
- APISIX는 ironclad 자산만 — netbis NPM 트래픽은 APISIX를 통과하지 않음. APISIX limit-req / chaitin-waf / 자작 4종 시나리오는 ironclad 자체 워크로드 트래픽에만 적용
- ironclad CDN은 CF + BunnyCDN 병행 — 같은 origin으로 수렴하지만 entry는 두 갈래. zone 별 proxied on/off로 어느 entry를 거치는지 결정 (
inouter.com/anvil.it.com은 BunnyCDN 단독, 나머지 kappa zone은 CF) - OpenWrt 라우터(
192.168.9.1)는 양 CDN 엣지에서 들어오는 ironclad 트래픽의 KR 진입점 — DNAT/HAProxy 통과 layer라 CrowdSec decision enforce 안 함 (별건 검토 필요)
관련 정본
- ../services/netbis — netbis 도메인/zone/NPM 호스트 상세
- ../services/bunnycdn-security — ironclad 자체 풀존 (iron-jp/iron-kr 등) 보안 layer
- security/crowdsec-safeline — CrowdSec acquisition / 시나리오 / netbis-cf-firewall
- security/cloudflare — ironclad CF zone / Workers / Turnstile
- compute/zlambda — 다리 호스트 상세
- compute/infra-hosts — incus / K3s 호스트 전반
- ../history/2026-04-23-netbis-npm-vl-collection
- ../history/2026-04-23-netbis-firewall-bouncer-migration
- ../history/2026-04-25-netbis-cf-firewall-rebuild
- ../history/2026-04-25-netbis-npm-vector-msg-rewrite
- ../history/2026-04-26-bouncer-consolidation