installer-pf: accurate CGNAT detection via router WAN vs public IP

리뷰 지적 반영. 기존엔 HTTP 공인 egress IP 만 100.64/10 검사라, 전형적 CGNAT
(egress 는 ISP 공인, 라우터 WAN 만 100.64)을 놓치고 "CGNAT 아님"처럼 오진 가능.
- 라우터 WAN(IGD 외부) IP 를 UPnP 로 조회해 HTTP 공인 IP 와 비교.
- cgnat 를 3-state(yes/no/unknown)로: WAN 이 사설/CGNAT 이거나 공인 IP 와 다르면
  yes, 같으면 no, WAN 못 읽으면 unknown.
- unknown 이면 "외부 IP만으론 CGNAT 확정/배제 불가, 라우터 WAN 확인" 안내.
- WAN 조회 타임아웃 8s→6s. v0.3.17.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This commit is contained in:
2026-07-05 21:26:13 +09:00
parent 05a5dcedc0
commit 005c7bf44c
5 changed files with 52 additions and 17 deletions

View File

@@ -112,9 +112,12 @@ function renderMain() {
// 실패/확인불가일 때 다음 조치 안내: CGNAT 경고 + 수동 포워딩 방법.
var extra = ''
if (outcome.reachable !== true) {
if (outcome.cgnat) {
if (outcome.cgnat === 'yes') {
extra += '<p class="formMessage error" style="margin-top:8px;">' +
escapeHtml(tt('main.cgnatWarn', { ip: outcome.externalIp || '?' })) + '</p>'
escapeHtml(tt('main.cgnatWarn', { public: outcome.externalIp || '?', wan: outcome.wanIp || '?' })) + '</p>'
} else if (outcome.cgnat === 'unknown') {
extra += '<p class="formMessage" style="margin-top:8px;">' +
escapeHtml(tt('main.cgnatUnknown', { ip: outcome.externalIp || '?' })) + '</p>'
}
var manual = outcome.localIp
? tt('main.manualForward', { port: outcome.port, localIp: outcome.localIp })