Switched Bunny iron-kr-nowaf origin from :443 (Traefik) to :9443 (APISIX, no SafeLine plugin) since APISIX plugins are per-route. Used existing :9443 path (juiceshop already there) instead of opening a new OpenWrt port. Outline route managed via ApisixTls + ApisixRoute CRDs because admin-API direct PUTs get swept by apisix-ingress-controller as orphans. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
82 lines
4.0 KiB
Markdown
82 lines
4.0 KiB
Markdown
---
|
|
date: 2026-04-21
|
|
topic: Outline을 WAF 없는 전용 Bunny 풀존(iron-kr-nowaf)으로 분리
|
|
areas:
|
|
- infra/platform/outline
|
|
- services/bunnycdn-security
|
|
---
|
|
|
|
# 2026-04-21 Outline Bunny 풀존 분리
|
|
|
|
`outline.inouter.com`을 WAF 없는 신규 풀존 `iron-kr-nowaf`로 이전. iron-kr의 7개 CRS 룰 복원.
|
|
|
|
## 배경
|
|
|
|
2026-04-13 iron-kr Shield learning mode 종료 후 CRS 룰이 enforce로 전환되면서 Outline API JSON 요청에 다수 오탐 누적:
|
|
|
|
| 룰 | 오탐 경로 | 누적 |
|
|
|---|---|---|
|
|
| 942100 libinjection SQLi | `api/*.list`, `api/collections.list` | 9 |
|
|
| 932235 Unix CMD Injection | `api/documents.create` | 3 |
|
|
| 932370 Windows CMD Injection | `api/documents.create` | 2 |
|
|
| 930130 Restricted File Access | `api/*` | 2 |
|
|
| 932230 Unix CMD Injection (2-3 chars) | `api/documents.create` | 1 |
|
|
| 933160 PHP Injection | `api/documents.create` | 1 |
|
|
|
|
Outline API는 Bearer 토큰 강제 인증 — WAF가 추가 보호 거의 없고 오탐만 생성.
|
|
|
|
Basic plan 한계로 host-per-path 커스텀 룰 불가, 따라서 **전용 풀존 분리** 채택.
|
|
|
|
## 변경 내역
|
|
|
|
### Bunny
|
|
|
|
| 항목 | 이전 | 이후 |
|
|
|---|---|---|
|
|
| Pull Zone | iron-kr (ID 5555227) | **iron-kr-nowaf** (ID 5720695, 신규) |
|
|
| Shield | iron-kr Shield 101015 (CRS 활성) | Shield 없음 |
|
|
| 국가차단 | middleware 64811 | middleware 64811 (동일) |
|
|
| OriginUrl | https://220.120.65.245 (Traefik 직결) | **https://220.120.65.245:9443** (APISIX 경유) |
|
|
| Backend 경로 | OpenWrt :443 → HAProxy → Traefik 192.168.9.53:443 → outline IngressRoute | OpenWrt :9443 → HAProxy → APISIX 192.168.9.50:443 → ApisixRoute outline → outline svc |
|
|
| AddHostHeader | true | true |
|
|
| VerifyOriginSSL | false | false |
|
|
| EnableWebSockets | true | true |
|
|
| TLS 인증서 | LE 자동 | `*.inouter.com` wildcard (cert-manager 수동 업로드) |
|
|
|
|
### APISIX (서울 K3s)
|
|
|
|
CRD 기반으로 관리 (admin API 직접 PUT은 apisix-ingress-controller가 orphan으로 판단해 sweep함):
|
|
|
|
| 객체 | 종류 | 이름 | 비고 |
|
|
|---|---|---|---|
|
|
| SSL | `ApisixTls` | `outline-tls` | sni=`outline.inouter.com`, secret=`apisix/wildcard-inouter-tls`, ssl_id=`4e7704e0` |
|
|
| Route | `ApisixRoute` | `outline` | host=`outline.inouter.com`, upstream=`outline.outline.svc:80`, plugins 없음(SafeLine 미장착), route_id=`ce4d2d80` |
|
|
| Class | `ingressClassName: apisix` | | apisix-ingress-controller가 reconcile |
|
|
|
|
⚠️ **중요**: APISIX 객체를 admin API로 직접 PUT하면 `apisix-ingress-controller`가 ingressClassName 없는 orphan으로 판단해 자동 DELETE함. 반드시 ApisixTls/ApisixRoute CRD 사용.
|
|
|
|
### DNS
|
|
|
|
```
|
|
outline.inouter.com CNAME iron-kr.b-cdn.net → iron-kr-nowaf.b-cdn.net
|
|
```
|
|
|
|
Cloudflare zone `inouter.com` (id cd84743d9c61b97bada5ce903a29ae2b), record id cb8fd1cf67b872e52600e4f868a2a992.
|
|
|
|
### iron-kr Shield 복원
|
|
|
|
임시 적용했던 `wafDisabledRules: [942100, 932230, 932235, 932260, 932370, 932380, 933160]` 전부 해제 → vault/n8n/telegram-webhook/jarvis 호스트 보호 원상복구.
|
|
|
|
## 검증
|
|
|
|
- `list_collections` MCP 호출 200 OK (이전 942100 차단)
|
|
- `create_document` 성공 (doc id `4bfff4c7-2fd3-478e-af00-2e25301da781` YouTube 요약)
|
|
- TLS cert SAN: `DNS:inouter.com, DNS:*.inouter.com` (GTS WR1, 만료 2026-06-21)
|
|
- HTTP/2 200, `cdn-pullzone: 5720695` 응답 헤더 확인
|
|
|
|
## 미해결 / 후속
|
|
|
|
- **Bunny LE 자동 발급 실패** — `POST /pullzone/loadFreeCertificate?hostname=outline.inouter.com`가 `The request is invalid` 반환 (원인 불명). 현재 *.inouter.com wildcard로 우회했지만 LE 자동 갱신 체계 구축하려면 재조사 필요. cert-manager 와일드카드 갱신이 2026-06-21 전에 Bunny에 재업로드 필요 — 자동화 스크립트 또는 cert-manager webhook 연동 검토
|
|
- Advanced plan 업그레이드 시 iron-kr에서 host-per-path 커스텀 룰로 통합 관리 가능 (현재는 풀존 2개 운영)
|
|
- 이번 이슈 원인 분석과 932380 n8n/vault 21건 실제 공격 건은 별도 Outline 문서로 보존: doc `ac429f1b-...`, doc `7ac9ec42-...`
|