diff --git a/infra/apisix.md b/infra/apisix.md index 0058d5e..334e17d 100644 --- a/infra/apisix.md +++ b/infra/apisix.md @@ -54,6 +54,24 @@ BunnyCDN(inouter, ID 5316471) → apisix-osaka(172.233.93.180) → 백엔드 - 2026-03-25 메인 라우팅 역할을 Traefik으로 이전, APISIX는 SafeLine WAF 전용으로 축소 - Ingress Controller + Gateway API CRD 제거됨 (GatewayProxy 모드에서 ApisixRoute CRD 미지원, HTTPRoute에 플러그인 개별 적용 불가 문제) +#### plugin_metadata (etcd 직접 등록) + +chaitin-waf 플러그인은 `plugin_attr`(config.yaml)이 아닌 **`plugin_metadata`(etcd)**에서 detector 노드를 읽음. 반드시 etcd에 등록해야 함. + +``` +etcdctl put /apisix/plugin_metadata/chaitin-waf '{"id":"chaitin-waf","nodes":[{"host":"10.43.253.244","port":8000}],"config":{"connect_timeout":1000,"send_timeout":1000,"read_timeout":1000,"req_body_size":1024,"real_client_ip":true}}' +``` + +#### 등록된 라우트 (etcd 직접 등록) + +| Route ID | 호스트 | upstream | chaitin-waf | 비고 | +|----------|--------|----------|-------------|------| +| juiceshop | juiceshop.keepanker.cv | juiceshop:3000 (juiceshop ns) | block | WAF 테스트용 OWASP Juice Shop | + +#### real_ip 설정 (ConfigMap 직접 수정) + +`real_ip_header: X-Forwarded-For`, `real_ip_from: 0.0.0.0/0` (BunnyCDN 경유이므로 전체 허용). Helm values로는 반영 안 되어 ConfigMap 직접 패치. + #### 이전 사유 (2026-03-25) - Ingress Controller 2.0 GatewayProxy 모드가 ApisixRoute CRD를 sync하지 않음 - Gateway API HTTPRoute에 플러그인 개별 적용 방법이 없음 diff --git a/infra/crowdsec-safeline.md b/infra/crowdsec-safeline.md index 3e85229..243b659 100644 --- a/infra/crowdsec-safeline.md +++ b/infra/crowdsec-safeline.md @@ -83,7 +83,33 @@ Bouncer 목록: [[apisix]]-waf-bouncer, bunny-cdn-bouncer, cs-[[cloudflare|cf]]- | NoSQLi (JSON) | 401 | 통과 (PostgreSQL이라 무효, 인증에서 차단) | | WP scan | 404 | 통과 (존재하지 않는 경로) | +### waf-kr BunnyCDN Pull Zone (2026-03-25) + +APISIX SafeLine WAF 전용 CDN zone. + +| 항목 | 값 | +|------|-----| +| Zone ID | 5554681 | +| Name | waf-kr | +| Origin | https://220.120.65.245:9443 | +| 경로 | 인터넷 → BunnyCDN(waf-kr) → OpenWrt HAProxy(:9443) → APISIX NodePort(31137) → SafeLine WAF → K3s 서비스 | + +등록된 호스트: `juiceshop.keepanker.cv` (OWASP Juice Shop, WAF 테스트용) + +### Juice Shop WAF 테스트 결과 (2026-03-25) + +| 요청 | 결과 | WAF Action | +|------|------|------------| +| 일반 GET / | 200 | pass | +| SQLi (`?id=1 OR 1=1`) | 403 | reject (SafeLine) | +| XSS (`?q=`) | 403 | reject (SafeLine) | + +### 다음 단계: CrowdSec 자동 차단 + +계획: SafeLine WAF 차단 로그 → APISIX http-logger → jp1 CrowdSec → 커스텀 시나리오 (3회 차단 시 ban) → bouncer로 APISIX ip-restriction 적용 + ### 참고 - BunnyCDN WAF 차단 시 오리진에 로그 안 옴 → CrowdSec에 미수신 - 리얼 IP: 외부 트래픽은 `X-Forwarded-For`로 정상 전달, LAN은 `127.0.0.1` - OpenWrt에 CrowdSec firewall bouncer 설치 가능하나 DNAT 구조라 리얼 IP 매칭 불가 +- chaitin-waf 플러그인은 `plugin_attr`이 아닌 **`plugin_metadata`(etcd)**에서 detector 노드를 읽음 — 주의 diff --git a/infra/openwrt.md b/infra/openwrt.md index 9ee128b..ecabcdf 100644 --- a/infra/openwrt.md +++ b/infra/openwrt.md @@ -88,6 +88,19 @@ WAN TCP 80/443 → 192.168.9.1:80/443 (HAProxy)로 DNAT. | 03:30 | `/usr/local/bin/backup-openwrt.sh` | 설정 백업 → NAS | | 04:00 | `/etc/cdn-filter-update.sh` | BunnyCDN+Cloudflare IP 갱신 | +## WAN DNAT (fw4) + +`/etc/config/firewall`의 redirect 규칙. firewall restart 시 `dstnat_wan` 체인에 반영. + +| Name | Port | 대상 | 비고 | +|------|------|------|------| +| APISIX-HTTP | :80 | 192.168.9.1:80 | Traefik 메인 | +| APISIX-HTTPS | :443 | 192.168.9.1:443 | Traefik 메인 | +| APISIX-WAF-HTTP | :9080 | 192.168.9.1:9080 | APISIX WAF | +| APISIX-WAF-HTTPS | :9443 | 192.168.9.1:9443 | APISIX WAF | + +DNAT 없으면 `input_wan` → `reject_from_wan`으로 차단됨. DNAT이 있어야 `ct status dnat accept`로 통과. + ## 관련 문서 - [[infra-hosts]] — 서버 목록