Skip to content

Releases: Control-D-Inc/ctrld

Release v1.5.4

Choose a tag to compare

@cuonglm cuonglm released this 14 Jul 14:07
d7f43ea

Minor Release

This contains some bug fixes.

Fixed

  • Fix macOS pf watchdog exec storms.
  • Add Windows NRPT recovery circuit breaker to prevent recovery loop.

Release v1.5.3

Choose a tag to compare

@cuonglm cuonglm released this 22 Jun 07:41
5bf26da

Minor Release

This contains new features, significant performance improvements, and bug fixes.

Security

  • Upgraded quic-go to v0.59.1 to address CVE-2026-40898

  • Rejected oversized upstream DNS responses on the DoH, DoH3, and DoQ paths — these previously used io.ReadAll on attacker-controlled responses before enforcing any protocol-level limit, allowing a malicious or compromised upstream to force unbounded buffering. Bodies are now capped at dns.MaxMsgSize (and non-200 DoH error bodies are bounded as well)

  • Validated DNS-over-QUIC response framing (RFC 9250) — the resolver previously assumed at least two bytes were present and could panic on truncated or malicious replies; the length prefix is now validated and framing failures retire the connection from the pool

  • Rate-limited PIN attempts on the control socket to provide defense-in-depth against brute-force if an attacker gains socket access

  • Switched temp file creation to os.CreateTemp for symlink-safe writes, preventing symlink attacks on systems without fs.protected_symlinks (e.g. embedded routers)

  • Switched internal/router/dnsmasq to text/template instead of html/template, since the generated config is plain text

Improved

  • Shared a single QUIC transport and UDP socket across DoQ dials so parallel dial and reconnect churn no longer allocate a socket per attempt or leak sockets; the query stream's send side is now closed before reading the response per RFC 9250 §4.2

  • Updated the Docker base image to bookworm

Fixed

  • Refreshed macOS VPN DNS after pf stabilization

  • Allowed intercept fallback for the default listener

  • Flushed pf states after a forced DNS intercept reload

Release v1.5.2

Choose a tag to compare

@cuonglm cuonglm released this 02 Jun 07:25
d629ecd

Minor Release

This release contains a bug fix for Windows platform.

Fixed

  • Fixes Windows DNS-intercept behavior for AD/internal split-rule domains during sleep/wake or VPN adapter settling without relying on a fixed timeout.

Release v1.5.1

Choose a tag to compare

@cuonglm cuonglm released this 25 May 11:11
7e6f88b

Minor Release

This contains bug fixes and a new diagnostic command.

Added

  • Added ctrld log tail command for live log streaming — streams runtime debug logs to the terminal in real-time, similar to tail -f. Supports --lines/-n flag to control initial context lines
  • Added WFP loopback protect for VPN block-outside-dns in dns intercept mode.

Improved

  • Configured QUIC keep-alive for DoQ connections — sends periodic PING frames (KeepAlivePeriod: 15s) on idle pooled connections, keeping them alive across NAT rebinding and proactively detecting dead paths before the next query hits a stale connection

Fixed

  • Fixed handle leak in hasLocalDnsServerRunning() on Windows — the process snapshot handle from CreateToolhelp32Snapshot was not being closed, leaking a handle on every call

  • Fixed dnsFromResolvConf not filtering loopback IPs — the continue statement only broke out of the inner loop, allowing loopback addresses (e.g. 127.0.0.1) through. This caused ctrld to use itself as bootstrap DNS when already installed as the system resolver, creating a self-referential loop

  • Fixed IPv6 VPN DNS server addresses not formatted correctly on macOS — upstreamConfigFor() passed bare IPv6 addresses to net.Dial without brackets or port, causing too many colons in address errors and immediate failure for all IPv6 VPN DNS queries

  • Fixed DNS responses failing with sendmsg: invalid argument for IPv6-sourced clients on macOS — the pf nat rule on lo0 inet6 did not match packets arriving via the rdr chain as inet4, so the client's global IPv6 source address was preserved, and the kernel rejected responses from [::1]:53 to non-loopback destinations

  • Fixed VPN DNS queries routed over wrong source interface on macOS — when a VPN client (e.g. FortiClient) was active, DNS queries to LAN servers used the VPN tunnel IP as source, making responses unroutable. Combined with the IPv6 bugs, this cascaded into complete VPN DNS failure and VPN disconnection

  • Fixed DoQ queries failing with idle timeout errors — pooled QUIC connections that timed out server-side now trigger a transparent retry with a fresh connection instead of propagating the error

  • Fixed DoQ queries failing with too many open streams — replaced non-blocking OpenStream with OpenStreamSync, which waits for the server's MAX_STREAMS credit replenishment instead of racing against it. Added StreamLimitReachedError as a retry condition for defense-in-depth when the stream credit wait times outetS

  • Fixed a crash in SetSelfIP triggered by network transitions before clientinfo initialization.

  • Fixed a recovery race condition, reduce worst-case recovery from ~30s to <3s.

Release v1.5.0

Choose a tag to compare

@cuonglm cuonglm released this 04 Mar 13:57
2926c76

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 + rdr rules, _ctrld group 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
  • 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 scutil ComputerName instead of os.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.EOF errors 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

Release v1.4.9

Choose a tag to compare

@cuonglm cuonglm released this 13 Jan 14:43
d034149

Minor Release

This contains new features, improvements and bug fixes.

Added

  • We’ve updated ctrld to send system metadata when calling the Control D API, allowing for a more seamless and personalized UX.
  • Added new documentation for internal runtime logging to clarify how it works and how it interacts with other logging configurations.

Improvements

  • Upgrade the quic-go library to v0.57.1 to resolve a critical bug in parsing HTTP3 frame header.

Fixes

  • Fixed a bug where DoH3 connections were closed incorrectly, preventing ctrld from recovering during network outages.

Release v1.4.8

Choose a tag to compare

@cuonglm cuonglm released this 02 Dec 14:40
57a9bb9

Minor Release

This contains improvements and bug fixes.

Improvements

  • Upgrade the quic-go library to v0.56.0 to improve API usability and resolve several critical bugs.

Fixes

  • Fixed a bug that allowed the root domain to be passed to systemd-resolved, which subsequently caused DNS resolution failure on Linux.
  • Fixed a bug where log flags were not processed during a reloading operation, causing internal runtime logging to fail after the reload completed.

Release v1.4.7

Choose a tag to compare

@cuonglm cuonglm released this 06 Oct 18:03
3ca559e

Minor Release

This contains new features and improvements.

Added

  • Make RFC1918 listener spawning opt-in via --rfc1918 flag instead of automatic behavior.
  • Add the Darwin 15.5 upgrade issue to the known issues documentation.
  • The mobile library can now be initiated with a provision ID and custom hostname.

Improvements

  • Upgrade the quic-go library to v0.54.0 to improve API usability and resolve several bugs.

Fixes

  • A bug was fixed where ctrld would incorrectly listen on RFC1918 addresses associated with virtual interfaces. This behavior caused unnecessary delays in resolving DNS queries, especially when those virtual interfaces were not active.

Release v1.4.6

Choose a tag to compare

@cuonglm cuonglm released this 21 Aug 21:10
eb2b231

Minor Release

This contains improvements and bug fixes.

Added

  • Support for OPNsense 25.1.7 was added via a new lease file (@jquick).

Improvements

  • Moved network monitoring creation to a dedicated goroutine for better performance and to ensure only a single instance is started.

Fixed

  • Corrected an issue where Windows domain join status was not being detected properly.
  • Addressed a bug where the upstream process check failed when attempting to process large DNS responses.

Release v1.4.5

Choose a tag to compare

@cuonglm cuonglm released this 24 Jul 21:07
26257cf

Minor Release

This contains new features, and improvements..

Added.

  • Major version upgrades are prohibited to avoid introducing breaking changes

Fixed

  • Support Merlin 3006 base firmware.
  • Support Ubios 4.3+.
  • Addressed a regression preventing ctrld start from successfully initializing with an empty positional argument.