- Bound public-IP detection with a 10s timeout context. The HTTP
fallback chain in getIP could otherwise block proxy startup
indefinitely on slow endpoints; the old single DNS lookup could
not. Plumbed via context through getIP/fetchPublicIP and added
context.WithTimeout in warnSNIMismatch, checkSecretHost, and
Access.Run.
- Emit a dedicated warning in warnSNIMismatch when the secret
hostname resolves successfully but to zero addresses, mirroring
the doctor's tplEDNSSNINoResolve branch instead of falling
through to a mismatch warning with an empty resolved list.
- Allow configuring network.public-ip-endpoints (TOML) /
publicIpEndpoints (JSON) so deployments can override the default
list (ifconfig.co, icanhazip.com, ifconfig.me). The default is
preserved when the option is omitted.
The runtime warning (warnSNIMismatch) and the diagnostic command
(doctor checkSecretHost) previously implemented the same SNI-DNS
check with different logic: the runtime path was tightened in #461
to require every detected IP family to match, but the doctor still
accepted any single match. The two now agree.
Changes:
- Extract the shared check into internal/cli/sni_check.go, returning
the resolved addresses and a per-family match status.
- Rewrite warnSNIMismatch and checkSecretHost on top of the helper.
- Doctor output now reports the mismatched IP family (IPv4, IPv6, or
both) and lists the server's public IP alongside the DNS result.
- getIP falls back through a short list of public-IP endpoints
(ifconfig.co, icanhazip.com, ifconfig.me) instead of relying on
a single third-party service.