Files
obsidian/infra/domain-boundaries.md
kaffa b9300e6798 domain-boundaries: ironclad 자체 cycle 추가
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로 분리해 명시
추적 시 주의 항목 보강
2026-04-27 07:44:24 +09:00

217 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 도메인 경계 — netbis vs ironclad (cross-domain 운영)
updated: 2026-04-27 ironclad 자체 cycle 추가 (CF + BunnyCDN 병행, OpenWrt → K3s APISIX+SafeLine, enforce layer 재구축 미정)
tags: [infra, domain, netbis, ironclad, zlambda, moc]
---
# 도메인 경계와 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](https://dash.bunny.net/support/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 정본]] — netbis 도메인/zone/NPM 호스트 상세
- [[../services/bunnycdn-security|BunnyCDN 보안]] — ironclad 자체 풀존 (iron-jp/iron-kr 등) 보안 layer
- [[security/crowdsec-safeline|CrowdSec / SafeLine]] — CrowdSec acquisition / 시나리오 / netbis-cf-firewall
- [[security/cloudflare|Cloudflare (kappa account)]] — ironclad CF zone / Workers / Turnstile
- [[compute/zlambda|zlambda]] — 다리 호스트 상세
- [[compute/infra-hosts|인프라 호스트 인덱스]] — incus / K3s 호스트 전반
- [[../history/2026-04-23-netbis-npm-vl-collection|history: NPM → VL 수집 도입]]
- [[../history/2026-04-23-netbis-firewall-bouncer-migration|history: netbis-cf-firewall 마이그레이션]]
- [[../history/2026-04-25-netbis-cf-firewall-rebuild|history: netbis-cf-firewall 재구축]]
- [[../history/2026-04-25-netbis-npm-vector-msg-rewrite|history: NPM Vector _msg 재합성]]
- [[../history/2026-04-26-bouncer-consolidation|history: bouncer 단일화]]