Major Release
This contains new features, significant performance improvements, and bug fixes.
Added
-
Added DNS intercept mode (
--intercept-mode=dns|hard|off) — a major new feature that intercepts all DNS traffic on the system and routes it through ctrld- macOS: pf-based interception with
route-to lo0+rdrrules,_ctrldgroup exemption, watchdog auto-heal for Parallels VM pf corruption, and IPv6 DNS blocking - Windows: dual-mode support — NRPT for standard DNS interception, WFP sublayer with callout filters for hard interception
- VPN DNS split routing — discovers DNS servers from F5 BIG-IP, Tailscale, Network Extension VPNs, and traditional VPN adapters; handles split vs full tunnel detection; cleans up stale exemptions on VPN disconnect
- Recovery bypass for captive portals and probe-based interception verification
- macOS: pf-based interception with
-
Added robust platform-specific username detection for Control D metadata (macOS: directory services/console user, Linux: loginctl/utmp/passwd, Windows: WTS/registry/token)
-
Added hostname hints in provisioning metadata for API-side fallback, allowing the server to repair generic hostnames
Improved
-
Implemented connection pooling for DoQ (QUIC) — eliminates per-query handshake overhead by reusing connections, matching DoH3 performance
-
Implemented connection pooling for DoT (TLS) — eliminates per-query TLS handshake overhead by reusing connections
-
Improved DNS server discovery for domain-joined Windows machines — non-physical adapters with matching DNS suffix are now considered valid for remote VPN scenarios
-
Consolidated network change monitoring into a single goroutine for simpler, more reliable handling
Fixed
-
Fixed macOS hostname detection — uses
scutilComputerName instead ofos.Hostname(), which returns generic names like "Mac.lan" when Private Wi-Fi Address is enabled -
Fixed DoT connection validation — connections are now checked before reuse to prevent
io.EOFerrors from server-side idle timeouts -
Fixed handling of empty and invalid IP addresses to prevent panics when processing client info
-
Fixed a data race in transport rebootstrap using a three-state atomic instead of a boolean flag