[CLAUDE] Scripts+Skill+Docs: hardening G-084 IPv4/IPv6 port hijack
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m53s

Bài học từ VietReport VPS shared (2026-04-23): Next.js app hijack port
3000 IPv4 → Gitea bị đẩy IPv6-only → IIS ARR localhost:3000 resolve
IPv4 first → git.baocaogiaoduc.vn trả homepage VietReport.

Apply 3 rules G-084 preemptively cho SOLUTION_ERP (risk thấp vì API
in-process IIS, nhưng vẫn chuẩn hóa):

1. `scripts/deploy-iis.ps1` — HealthUrl `localhost` → `127.0.0.1`
2. `.claude/skills/iis-deploy-runbook/SKILL.md` — 7 ref localhost →
   127.0.0.1 + section Hardening mới giải thích G-084 + 3 rules + note
   SOLUTION_ERP relevance (risk thấp vì no standalone Kestrel/no ARR
   proxy hiện tại, nhưng tương lai thêm phải tuân)
3. `docs/gotchas.md` — thêm entry #33 G-084 full writeup (triệu chứng,
   root cause, 3 rules, SOLUTION_ERP relevance) + update debug
   checklist

3 rules:
- Reverse-proxy luôn IP literal 127.0.0.1, không localhost
- Backend services bind loopback IPv4 explicit, không 0.0.0.0
- Service dependency cho boot order khi nhiều service cùng port family
This commit is contained in:
pqhuy1987
2026-04-23 17:34:22 +07:00
parent aaf03be8d7
commit 3990066b04
2 changed files with 73 additions and 8 deletions

View File

@ -300,6 +300,39 @@ Write-Host "Setup IIS sites done" # thay vi "Hoan tat"
<NavLink to={path} end={path.includes('?')}>
```
## IIS / Windows Server (continued)
### 33. IPv4/IPv6 port hijack trên VPS shared (G-084)
**Triệu chứng:** `git.baocaogiaoduc.vn` trả về homepage Next.js của VietReport
thay vì Gitea UI. Headers lộ `x-nextjs-cache: HIT` + `X-Powered-By: ARR/3.0`
(request đã qua IIS ARR proxy rồi mới hit Next.js).
**Root cause:** Next.js app (NSSM service) được deploy lên VPS shared với
Gitea, ignore env `PORT=3001 HOSTNAME=127.0.0.1` và bind `0.0.0.0:3000`.
Gitea bind `0.0.0.0:3000` trước đó bị Windows fallback xuống IPv6-only
`[::]:3000` (default `IPV6_V6ONLY=1`). IIS ARR rewrite `http://localhost:3000`
→ Windows DNS resolve IPv4 first → hit Next.js → leak homepage cho TẤT CẢ
subdomain có ARR proxy về `:3000`.
**Fix (VietReport applied):**
1. Next.js NSSM env `PORT=3001 HOSTNAME=127.0.0.1` — bind loopback IPv4
2. Gitea `HTTP_ADDR=127.0.0.1` — bind loopback IPv4 explicit
3. IIS `web.config` rewrite URL dùng `127.0.0.1` thay `localhost`
4. NSSM `DependOnService=gitea` — boot order tránh race
**3 rules rút ra — áp dụng mọi service trên VPS shared:**
- Reverse-proxy luôn **IP literal `127.0.0.1`**, KHÔNG dùng `localhost`
- Backend services bind **loopback IPv4 explicit**, KHÔNG `0.0.0.0`
- Service dependency cho boot order khi nhiều service cùng port family
**SOLUTION_ERP relevance:**
- API host trong IIS app pool out-of-process (ANCM tự quản lý port Kestrel ephemeral) → risk THẤP
- FE gọi trực tiếp `https://api.huypham.vn` (không ARR proxy) → risk THẤP
- **NHƯNG** nếu tương lai thêm ARR reverse proxy (fe-admin/user `/api` proxy) hoặc
deploy Kestrel standalone qua NSSM → PHẢI apply 3 rules trên
- Scripts + skill doc đã update `localhost``127.0.0.1` để đồng bộ
## Checklist debug bug mới
1. Build pass không? → fail → check using + package version compat
@ -313,3 +346,4 @@ Write-Host "Setup IIS sites done" # thay vi "Hoan tat"
9. Nếu workflow 403 → check FE `workflow.nextPhases` sync từ BE pinned policy
10. Nếu SignalR 401 → dùng `accessTokenFactory` + BE OnMessageReceived hook (#26)
11. Nếu PS 5.1 script fail → check encoding UTF-8 / BOM / ASCII-only (#30)
12. Nếu subdomain trả sai content / bị hijack → check IPv4/IPv6 port collision trên VPS shared (#33)