Files
obsidian/infra/security/cloudflare.md
kaffa 102da9c2fe cloudflare: Pseudo IPv4 (Class E 240/4) 정리 — Netbis 관찰 기반
- infra/security/cloudflare.md: Pseudo IPv4 섹션 신규 (동작 원리·모드·함의·오해 주의)
- services/netbis.md: client_ip 의미에서 부정확한 '254.x 범위' → '240.0.0.0/4' 정정, CF docs 링크
- history: 2026-04-24 CF Pseudo IPv4 정체 규명 (CGNAT 오진 교훈 포함)
2026-04-24 08:11:44 +09:00

251 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: Cloudflare 서비스
updated: 2026-04-10
tags: [infra, cloudflare, cdn, dns]
---
Syn 이 엣지 관점에서 소유. 일반 DNS 관리 협업은 Heimdall.
## 계정
- ID: `d8e5997eb4040f8b489f09095c0f623c` (kappa@inouter.com)
- API 토큰: Vault `secret/cloud/cloudflare` (`api_token`, `email`)
### API 토큰 권한 범위 (2026-04-13 실측)
| 엔드포인트 | 권한 |
|-----------|------|
| Zone Read | ✅ |
| DNS Read/Write | ✅ |
| Turnstile Read | ✅ (Write는 ❌ 403) |
| Workers Read | ✅ |
| KV Read | ✅ |
| Rulesets (WAF/Rate Limit 규칙) | ❌ 403 |
| Firewall Rules | ❌ 403 |
| Rate Limits (legacy) | ❌ 403 |
| Zone Settings | ❌ 403 |
⚠️ **Rate Limit, WAF 규칙, Firewall 설정은 API로 조회/변경 불가 — 대시보드에서만 관리 가능**. 토큰 스코프 확장이 필요하면 CF 대시보드 > My Profile > API Tokens에서 편집.
## Pseudo IPv4 (Class E 240/4)
레거시 IPv4-only 백엔드를 위한 CF 기능. **Netbis zone에서 활성 상태로 관찰됨** (Apache 2.4.38 + PHP 5.6.40). Kappa 계정 zone에는 현재 기본 Off로 추정.
### 동작 원리
```
클라이언트 (IPv6) → CF 엣지
→ IPv6 주소 상위 64비트를 MD5 해시
→ 결과를 240.0.0.0/4 (240~255.x.x.x) 범위의 IPv4로 매핑
→ CF-Connecting-IP 및 X-Forwarded-For 헤더를 해시된 IPv4로 overwrite
→ 진짜 IPv6는 Cf-Connecting-IPv6 별도 헤더로 전달
```
### 모드 3종 (CF 대시보드 Network → Pseudo IPv4)
| 모드 | CF-Connecting-IP | 별도 헤더 |
|------|-----------------|----------|
| Off | 실 IPv6/IPv4 | - |
| Add header | 실 IP 그대로 | `Cf-Pseudo-IPv4`에 해시 |
| **Overwrite headers** | 해시(240/4) | `Cf-Connecting-IPv6`에 실 IPv6 |
### 관찰 시그널 (Netbis)
- VL `client_ip` 필드 중 240.0.0.0/4 대역 IP 등장 = IPv6 접속자
- UA 분포: 95%+ 모바일 (Android Chrome / iPhone Safari / KakaoTalk / Daum / NAVER) — KR 모바일 IPv6 보급률 높음
- 동일 IPv6 `/64` prefix → 항상 같은 240/4 IP로 매핑 (재현 가능한 식별자)
- **한 240/4 IP = 한 가정/ /64 단위 유저 집합** — ban 시 /64 전체가 차단됨
### 오해 주의
- 240/4는 KR 통신사 CGNAT 아님 (공식 문서 없음, 공개 라우팅도 안 됨)
- 실제로는 CF Pseudo IPv4 해시값 — "가짜 IP"
- CGNAT 오인하면 차단 효과 완전히 다르게 판단됨
### 관련 링크
- [CF Pseudo IPv4 docs](https://developers.cloudflare.com/network/pseudo-ipv4/)
- [CF Support: Pseudo IPv4 overview](https://support.cloudflare.com/hc/en-us/articles/229666767)
## Zone
| Zone | Zone ID | Status | Plan | NS | DNS rec | 비고 |
|---|---|---|---|---|---|---|
| **actions.it.com** | `dd7db273…` | active | Free | earl/raegan | 2 | apex+wildcard CNAME → BunnyCDN. `*.actions.it.com → actions.b-cdn.net` 는 dead 풀존 가리킴 (미정리) |
| **anvil.it.com** | `742f4c98…` | active | Free | earl/raegan | 9 | apex/wildcard CNAME → iron-jp, ssh.anvil.it.com A, Cloudflare Email Routing |
| **inouter.com** | `cd84743d…` | active | Free | earl/raegan | 32 | 메인 zone. 와일드카드 → k3s.inouter.com (LAN), 다수 서브가 iron-kr / iron-git 으로 분기 |
| **ironclad.it.com** | `bc8761b3…` | active | Free | earl/raegan | 14 | apex+wildcard A `172.233.93.180` (proxied), Mailgun MX, AWS SES DKIM |
| **keepanker.cv** | `118ac337…` | active | Free | lochlan/olivia | 3 | apex/wildcard → Cloudflare Tunnel (`cfargotunnel.com`), juiceshop CNAME → iron-kr-waf |
| **servidor.it.com** | `a6e1a3f1…` | active | Free | earl/raegan | 0 | DNS 0건 orphan. cert-manager wildcard + CrowdSec bouncer + Turnstile 위젯은 세팅된 상태 (배포 준비용 유지) |
별도 계정 [[netbis]] 의 6개 zone 은 본 문서 범위 외 — netbis-cf-bouncer 가 별도로 관리.
## DNS 레코드 — zone 별 핵심
### actions.it.com
| Name | Type | Value | Proxied |
|---|---|---|---|
| `actions.it.com` | CNAME | `iron-kr.b-cdn.net` | ✅ |
| `*.actions.it.com` | CNAME | `actions.b-cdn.net` (dead 풀존) | ✅ |
### anvil.it.com
| Name | Type | Value | Proxied |
|---|---|---|---|
| `anvil.it.com` | CNAME | `iron-jp.b-cdn.net` | off |
| `*.anvil.it.com` | CNAME | `iron-jp.b-cdn.net` | off |
| `n8n.anvil.it.com` | CNAME | `iron-jp.b-cdn.net` | off |
| `kroki.anvil.it.com` | CNAME | `k3s.inouter.com` | off |
| `ssh.anvil.it.com` | A | `139.162.71.52` | off |
| MX×3 Cloudflare Email Routing, DKIM TXT | | | |
### inouter.com
| Name | Type | Value | Proxied | 메모 |
|---|---|---|---|---|
| `*.inouter.com` | CNAME | `k3s.inouter.com` | off | LAN 직통 (BunnyCDN 우회) |
| `k3s.inouter.com` | A | `192.168.9.53` | off | Traefik MetalLB VIP |
| `kr.inouter.com` | A | `220.120.65.245` | off | OpenWrt 공인 IP |
| `jp.inouter.com` | A | `42.125.196.116` | off | jp1 |
| `derp.inouter.com` | A | `42.125.196.116` | off | jp1 derp |
| `gitea.inouter.com` | CNAME | `iron-git.b-cdn.net` | off | 별도 풀존 (미들웨어 우회) |
| `n8n.inouter.com` | CNAME | `iron-kr.b-cdn.net` | off | |
| `jarvis.inouter.com` | CNAME | `iron-kr.b-cdn.net` | off | |
| `vault.inouter.com` | CNAME | `iron-kr.b-cdn.net` | off | |
| `outline.inouter.com` | CNAME | `iron-kr.b-cdn.net` | off | |
| `telegram-webhook.inouter.com` | CNAME | `iron-kr.b-cdn.net` | off | |
| `desk-api.inouter.com` | A | `172.233.93.180` | ✅ | osaka 직통, CF proxied |
| `sftp.inouter.com` | A | `220.120.65.245` | ✅ | OpenWrt 직통, CF proxied |
| `git.inouter.com` | A | `52.79.45.166` | off | relay4wd Lightsail |
| `teleport.inouter.com` | A | `52.79.45.166` | off | relay4wd Lightsail |
| `twilio.jp.inouter.com` | A | `172.233.93.180` | off | |
| `bunny.mcp.inouter.com` | CNAME | `k3s.inouter.com` | off | |
| `vl.inouter.com` | CNAME | `k3s.inouter.com` | off | [[victorialogs|VictoriaLogs]] |
| `emulator.api.inouter.com` | CNAME | `k3s.inouter.com` | off | |
| `linode.api.inouter.com` | CNAME | `k3s.inouter.com` | off | |
| `namecheap.api.inouter.com` | CNAME | `k3s.inouter.com` | off | |
| `vultr.api.inouter.com` | CNAME | `k3s.inouter.com` | off | |
| `email.inouter.com` | CNAME | `mailgun.org` | off | |
| MX×2 Mailgun, TXT (SPF/DMARC/DKIM/google verification) | | | | |
`nas.inouter.com` 은 특정 A/CNAME 레코드 없음. `*.inouter.com` 와일드카드 폴백으로 `192.168.9.53` (LAN MetalLB VIP) 로 해석되어 K3s `lan-proxies/nas` IngressRoute 를 통해 Synology DSM (`192.168.9.100:5000`) 으로 reverse proxy. 상세 [[nas-storage#DSM Reverse Proxy — `nas.inouter.com`]].
### ironclad.it.com
| Name | Type | Value | Proxied |
|---|---|---|---|
| `ironclad.it.com` | A | `172.233.93.180` | ✅ |
| `*.ironclad.it.com` | A | `172.233.93.180` | ✅ |
| MX×2 Mailgun, AWS SES DKIM CNAME×3, TXT (SPF/DMARC/google) | | | |
ironclad.it.com 은 **BunnyCDN 풀존을 거치지 않음**. CF proxied A 로 osaka `172.233.93.180` 직통. 보호는 CF Worker (`ironclad-site` apex + bouncer wildcard) 단독.
### keepanker.cv
| Name | Type | Value | Proxied |
|---|---|---|---|
| `keepanker.cv` | CNAME | `f1aa79f2-….cfargotunnel.com` | ✅ |
| `*.keepanker.cv` | CNAME | `f1aa79f2-….cfargotunnel.com` | ✅ |
| `juiceshop.keepanker.cv` | CNAME | `iron-kr-waf.b-cdn.net` | off |
apex/wildcard 는 Cloudflare Tunnel. juiceshop 은 BunnyCDN iron-kr-waf 로 override.
### servidor.it.com
DNS 레코드 없음. zone 만 등록. 워커 라우트 + Turnstile 위젯 + cert-manager wildcard cert 는 세팅되어 있으며 배포 준비 상태로 유지.
## Workers
| Worker | 라우트 부착 zones | 비고 |
|---|---|---|
| **crowdsec-cloudflare-worker-bouncer** | actions, ironclad, keepanker, servidor | CrowdSec CF bouncer 본체. cs-cf-worker-bouncer (jp1) 가 168h 마다 secret rotate. 정본 [[crowdsec-safeline]] |
| **ironclad-site** | ironclad.it.com (apex) | 정적 사이트, has_assets |
| **cf-multisite** | `*.actions.it.com/*` | 라우팅 워커 |
| chat-worker | (없음) | workers.dev only |
| cloud-instances-api | (없음) | workers.dev only |
| cloud-orchestrator | (없음) | workers.dev only |
| telegram-ai-support | (없음) | workers.dev only |
| telegram-cli-web | (없음) | workers.dev only |
| telegram-summary-bot | (없음) | workers.dev only |
### Worker 라우트 (zone 별)
| Zone | Pattern | Script |
|---|---|---|
| actions.it.com | `*actions.it.com/*` | crowdsec-cloudflare-worker-bouncer |
| actions.it.com | `*.actions.it.com/*` | cf-multisite |
| actions.it.com | `vultr.actions.it.com/*` | null (orphan, 미정리) |
| actions.it.com | `linode.actions.it.com/*` | null (orphan, 미정리) |
| ironclad.it.com | `ironclad.it.com/*` | ironclad-site |
| ironclad.it.com | `*ironclad.it.com/*` | crowdsec-cloudflare-worker-bouncer |
| keepanker.cv | `*keepanker.cv/*` | crowdsec-cloudflare-worker-bouncer |
| servidor.it.com | `*servidor.it.com/*` | crowdsec-cloudflare-worker-bouncer |
inouter.com / anvil.it.com 에는 Worker 라우트 없음. DNS proxied=false 라 CF 엣지를 거치지 않으므로 enforce 불가 — 이들 zone 의 엣지 보호는 BunnyCDN 미들웨어 64811 이 단독 책임.
Worker Custom Domains (계정 레벨): 0건.
## Turnstile 위젯
| Sitekey | 이름 | mode | 도메인 | 역할 |
|---|---|---|---|---|
| `0x4AAAAAABvmO8BKc1ss5d-S` | `crowdsec-captcha` | managed | actions / anvil / charon.my / ironclad / keepanker / n8n.my / servidor / subin.my | multi-domain 운영용 (8 도메인). 수동 관리 (bouncer 외) |
| `0x4AAAAAACbmaudAjITah7y7` | `inouter` | managed | anvil.it.com | 이름·도메인 불일치 (legacy/orphan 후보, 결정 미정) |
| `0x4AAAAAAC3otPWhldI96Aks` | `inouter-bunny-middleware` | managed | inouter.com | BunnyCDN 미들웨어 64811 의 `TURNSTILE_SITE_KEY` / `TURNSTILE_SECRET_KEY` env baked-in. 이름이 bouncer auto 패턴과 달라 cs-cf-worker-bouncer 가 관리 대상 외. **수동 관리**, sitekey/secret 변경 시 미들웨어 64811 env 동시 갱신 필수 |
| `0x4AAAAAAC3nIMLBRKWfiY8A` | `crowdsec-cloudflare-worker-bouncer-widget` | managed | actions.it.com | cs-cf-worker-bouncer 자동 (168h rotation). 수동 편집 금지 |
| `0x4AAAAAAC3nIYV_A5OA0Xzv` | 〃 | managed | ironclad.it.com | 〃 |
| `0x4AAAAAAC3nHnAB6Q9dlvHM` | 〃 | managed | keepanker.cv | 〃 |
| `0x4AAAAAAC3nH0xXSU8kbwsn` | 〃 | managed | servidor.it.com | 〃 |
`inouter-bunny-middleware` 의 secret 은 Vault `secret/cloud/cloudflare/turnstile-inouter-bunny` (`sitekey`, `secret`, `name`).
### Turnstile 토큰 권한
- **Vault `secret/cloud/cloudflare.api_token`** (`pUIZdTV0…`): DNS R/W + Turnstile **read-only**. 위젯 생성/수정/삭제 불가
- **jp1 bouncer 호스트의 `/etc/crowdsec/bouncers/crowdsec-cloudflare-worker-bouncer.yaml``token: seUKZID4…`**: Turnstile **read+write**. bouncer 의 자체 인증 자산이며 Vault 에 복제되어 있지 않음
## 특이사항
- **`*.actions.it.com → actions.b-cdn.net`** — 와일드카드가 dead 풀존 가리킴. 일부 서브가 5xx 가능. 미정리 (영향 평가 후 별건)
- **Worker routes `vultr.actions.it.com/*`, `linode.actions.it.com/*`** — `script: null` orphan. 미정리
- **Turnstile `inouter` (`…CbmaudAjITah7y7`)** — 이름·도메인 불일치 legacy 후보. 미정리
### CF proxy on/off 패턴
| Zone | Proxy | 보호 |
|---|---|---|
| inouter.com / anvil.it.com | off | BunnyCDN 미들웨어 64811 단독 |
| actions.it.com / ironclad.it.com | on | CF Worker (bouncer + cf-multisite / ironclad-site) |
| keepanker.cv | on (Tunnel) | CF Tunnel + juiceshop 만 iron-kr-waf override |
## cfb-manager (CrowdSec CF Worker bouncer 관리 API)
| 항목 | 값 |
|---|---|
| 위치 | K3s `default/cfb-manager` (`10.43.68.76:8000`) |
| 구현 | Python FastAPI |
| 기능 | bouncer 보호 도메인 추가/삭제, decision 조회, CF zone 동기화, bouncer 재시작 트리거 |
| SSH 키 | K8s `default/cfb-ssh-key` (ed25519) |
```bash
BASE=http://cfb-manager.default.svc.cluster.local:8000
curl $BASE/status # bouncer_running, pids, protected_domains
curl $BASE/domains # 보호 중인 zone 상세
curl $BASE/decisions # 현재 결정
curl -X POST $BASE/domains/<zone> # zone 추가
curl -X DELETE $BASE/domains/<zone> # zone 제거 (destructive — bouncer restart + widget rotate)
```
**중요**: `DELETE /domains/<zone>` 는 단순 config 항목 제거가 아니라 bouncer restart 를 트리거하며, restart 가 모든 zone 의 widget 을 force-rotate 하고 제거된 zone 의 widget 을 destroy 한다. 외부에서 baked-in 으로 사용 중인 sitekey 가 있다면 동시에 깨진다.
BunnyCDN 미들웨어와는 무관. BunnyCDN 미들웨어 64811 의 bloom filter 동기화는 jp1 `infra-tool` 컨테이너 `/opt/crowdsec-bouncer/bouncer.py` (3분 delta + 매시 full sync) 가 담당.
## 관련 문서
- [[netbis]] — Netbis 계정 Cloudflare (별도)
- [[cf-multisite]] — `*.actions.it.com` 라우팅 워커
- [[crowdsec-safeline]] — CrowdSec CF Worker Bouncer 연동
- [[bunnycdn-security]] — BunnyCDN 엣지 보안
- [[nas-storage]] — Synology NAS + `nas.inouter.com` reverse proxy