Files
minecraft_launcher/src/installer-pf/preload.ts
claude-bot 005c7bf44c 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>
2026-07-05 21:26:13 +09:00

42 lines
1.2 KiB
TypeScript

import { contextBridge, ipcRenderer } from 'electron'
interface PortForwardOutcome {
externalIp: string
localIp: string
wanIp: string
cgnat: 'yes' | 'no' | 'unknown'
port: number
reachable: boolean | null
preForwarded: boolean
detail: string
}
const api = {
/** i18n 사전을 렌더러에 전달. */
loadLocale: (): Promise<Record<string, unknown>> => ipcRenderer.invoke('pf:i18n:dict'),
/** 지정 포트를 UPnP 로 개방 시도하고 외부에서 닿는지 점검. */
openPort: (port: number): Promise<PortForwardOutcome> => ipcRenderer.invoke('pf:open', port),
/** UPnP 포트 매핑 제거. */
closePort: (port: number): Promise<void> => ipcRenderer.invoke('pf:close', port),
/** 프로그램 종료. */
quit: (): Promise<void> => ipcRenderer.invoke('pf:quit'),
/** 로그 스트림 구독. */
onLog: (handler: (line: string) => void): (() => void) => {
const listener = (_event: unknown, line: string) => handler(line)
ipcRenderer.on('log', listener)
return () => ipcRenderer.removeListener('log', listener)
}
}
contextBridge.exposeInMainWorld('pfTool', api)
declare global {
interface Window {
pfTool: typeof api
}
}