Skip to content

Consolidate SNI-DNS check and tighten doctor#474

Draft
dolonet wants to merge 4 commits into9seconds:masterfrom
dolonet:feature/sni-connectivity-revisit
Draft

Consolidate SNI-DNS check and tighten doctor#474
dolonet wants to merge 4 commits into9seconds:masterfrom
dolonet:feature/sni-connectivity-revisit

Conversation

@dolonet
Copy link
Copy Markdown
Contributor

@dolonet dolonet commented Apr 22, 2026

Follow-up to #461. The runtime warning now requires every detected IP family to match, but mtg doctor still passes on any single match, and the detection logic is duplicated across the two sites.

This PR:

  • Extracts the shared SNI-DNS check into internal/cli/sni_check.go.
  • Rewrites warnSNIMismatch and Doctor.checkSecretHost on top of it, so doctor uses the same all-families-must-match rule.
  • Doctor output now names the mismatched family (IPv4/IPv6) and shows the server's public IP next to the resolved records.
  • getIP falls back through ifconfig.coicanhazip.comifconfig.me instead of depending on a single endpoint.

No connectivity-probe or policy changes beyond that — happy to split further if you'd prefer, or fold in more of what you had in mind with "the whole logic there must be revised, especially connectivity part."

dolonet added 2 commits April 22, 2026 08:44
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 9seconds#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.
Review follow-ups:

- Run the IPv4 and IPv6 detection in runSNICheck concurrently. With
  the new three-endpoint fallback in getIP, sequential detection could
  extend proxy startup by up to 30s per family on a slow/blocked
  network. Parallel detection bounds the worst case to roughly 30s
  total instead of 60s.
- Make sniCheckResult.OK() self-consistent: it now returns false when
  the hostname cannot be resolved or no public IP family is known,
  so callers cannot mistakenly treat 'cannot check' as 'all clear'.
@9seconds
Copy link
Copy Markdown
Owner

9seconds commented May 4, 2026

This one is draft so I skip it now

dolonet added 2 commits May 5, 2026 10:34
- 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.
Update example.config.toml: refresh the public-ipv4/public-ipv6
comment to mention the new multi-endpoint detection (no longer
solely ifconfig.co), and document the new
network.public-ip-endpoints option with the current default values.
@dolonet
Copy link
Copy Markdown
Contributor Author

dolonet commented May 5, 2026

Pushed a follow-up commit:

  1. Public-IP detection now runs under a 10s context.WithTimeout (in warnSNIMismatch, Doctor.checkSecretHost, Access.Run); ctx is plumbed through getIP/fetchPublicIP. Without it the new HTTP fallback chain could block startup indefinitely if all endpoints were slow.
  2. warnSNIMismatch now emits a dedicated warning when DNS resolves successfully to zero addresses, matching the doctor's tplEDNSSNINoResolve branch instead of printing a mismatch with an empty resolved list.
  3. Added network.public-ip-endpoints (TOML) / publicIpEndpoints (JSON) so the endpoint list is configurable. The current default (ifconfig.co, icanhazip.com, ifconfig.me) is preserved when omitted — but I'd like your call on what the default should be. Three third-party endpoints baked in feels borderline; happy to drop to one (e.g. icanhazip.com is Cloudflare-hosted and fairly neutral) or to none, requiring the operator to set public-ipv4/public-ipv6 explicitly. Whichever you prefer.

Will flip out of draft once #3 is settled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants