Commit Graph

842 Commits

Author SHA1 Message Date
Codescribe
768cc81855 feat: add Windows NRPT and WFP DNS interception
Implement DNS interception on Windows with dual-mode support:
- NRPT for --intercept-mode=dns: catch-all rule redirecting all DNS
  to ctrld's listener, with GP vs local path detection
- WFP for --intercept-mode=hard: sublayer with callout filters
  intercepting port 53 traffic
- NRPT probe-and-heal for async Group Policy refresh race
- Service registry verification for intercept mode persistence
- NRPT diagnostics script for troubleshooting

Includes WFP technical reference docs and Windows test scripts.

Squashed from intercept mode development on v1.0 branch (#497).
2026-03-03 14:29:09 +07:00
Codescribe
289a46dc2c feat: add macOS pf DNS interception
Implement DNS interception on macOS using pf (packet filter):
- Anchor injection into running ruleset (not /etc/pf.conf)
- route-to lo0 + rdr rules for locally-originated DNS capture
- _ctrld group exemption so ctrld's own queries bypass interception
- Watchdog to detect and restore wiped anchor rules
- Probe-based auto-heal for Parallels VM pf corruption
- IPv6 DNS blocking and block-return for clean timeouts
- Interface-specific tunnel detection for VPN coexistence
- Port 5354 fallback in intercept mode

Includes pf technical reference docs and test scripts.

Squashed from intercept mode development on v1.0 branch (#497).
2026-03-03 14:27:43 +07:00
Codescribe
1e8240bd1c feat: introduce DNS intercept mode infrastructure
Add --intercept-mode flag (dns/hard/off) with configuration support,
recovery bypass for captive portals, probe-based interception
verification, VPN DNS coexistence in the proxy layer, and IPv6
loopback listener guard.

Remove standalone mDNSResponder hack files — the port 53 binding
logic is now handled within the intercept mode infrastructure.

Squashed from intercept mode development on v1.0 branch (#497).
2026-03-03 14:26:39 +07:00
Codescribe
12715e6f24 fix: include hostname hints in metadata for API-side fallback
Send all available hostname sources (ComputerName, LocalHostName,
HostName, os.Hostname) in the metadata map when provisioning.
This allows the API to detect and repair generic hostnames like
'Mac' by picking the best available source server-side.

Belt and suspenders: preferredHostname() picks the right one
client-side, but metadata gives the API a second chance.
2026-03-03 14:25:53 +07:00
Codescribe
147106f2b9 fix(darwin): use scutil for provisioning hostname (#485)
macOS Sequoia with Private Wi-Fi Address enabled causes os.Hostname()
to return generic names like "Mac.lan" from DHCP instead of the real
computer name. The /utility provisioning endpoint sends this raw,
resulting in devices named "Mac-lan" in the dashboard.

Fallback chain: ComputerName → LocalHostName → os.Hostname()

LocalHostName can also be affected by DHCP. ComputerName is the
user-set display name from System Settings, fully immune to network state.
2026-03-03 14:25:41 +07:00
Cuong Manh Le
a4f0418811 fix(darwin): handle mDNSResponder on port 53 to avoid bind conflicts
When mDNSResponder is using port 53 on macOS, adjust listener config to
use 0.0.0.0:53, stop mDNSResponder before binding, and run cleanup on
install and uninstall so the DNS server can start reliably.
2026-03-03 14:25:25 +07:00
Cuong Manh Le
40c68a13a1 fix(metadata): detect login user via logname when running under sudo
On Darwin 26.2+, sudo no longer preserves SUDO_USER, LOGNAME, and USER
(CVE-2025-43416), so env-based detection fails. Use the logname(1)
command on Unix first, then fall back to environment variables and
user.Current() so the real login user is still reported correctly.
2026-03-03 14:25:11 +07:00
Cuong Manh Le
3f30ec30d8 refactor(doq): simplify DoQ connection pool implementation
Replace the map-based pool and refCount bookkeeping with a channel-based
pool. Drop the closed state, per-connection address tracking, and extra
mutexes so the pool relies on the channel for concurrency and lifecycle,
matching the approach used in the DoT pool.
2026-03-03 14:24:50 +07:00
Cuong Manh Le
4790eb2c88 refactor(dot): simplify DoT connection pool implementation
Replace the map-based pool and refCount bookkeeping with a channel-based
pool. Drop the closed state, per-connection address tracking, and
extra mutexes so the pool relies on the channel for concurrency and
lifecycle.
2026-03-03 14:24:39 +07:00
Cuong Manh Le
da3ea05763 fix(dot): validate connections before reuse to prevent io.EOF errors
Add connection health check in getConn to validate TLS connections
before reusing them from the pool. This prevents io.EOF errors when
reusing connections that were closed by the server (e.g., due to idle
timeout).
2026-03-03 14:24:27 +07:00
Cuong Manh Le
209c9211b9 fix(dns): handle empty and invalid IP addresses gracefully
Add guard checks to prevent panics when processing client info with
empty IP addresses. Replace netip.MustParseAddr with ParseAddr to
handle invalid IP addresses gracefully instead of panicking.

Add test to verify queryFromSelf handles IP addresses safely.
2026-03-03 14:24:07 +07:00
Cuong Manh Le
acbebcf7c2 perf(dot): implement connection pooling for improved performance
Implement TCP/TLS connection pooling for DoT resolver to match DoQ
performance. Previously, DoT created a new TCP/TLS connection for every
DNS query, incurring significant TLS handshake overhead. Now connections are
reused across queries, eliminating this overhead for subsequent requests.

The implementation follows the same pattern as DoQ, using parallel dialing
and connection pooling to achieve comparable performance characteristics.
2026-03-03 14:22:55 +07:00
Cuong Manh Le
2e8a0f00a0 fix(config): use three-state atomic for rebootstrap to prevent data race
Replace boolean rebootstrap flag with a three-state atomic integer to
prevent concurrent SetupTransport calls during rebootstrap. The atomic
state machine ensures only one goroutine can proceed from "started" to
"in progress", eliminating the need for a mutex while maintaining
thread safety.

States: NotStarted -> Started -> InProgress -> NotStarted

Note that the race condition is still acceptable because any additional
transports created during the race are functional. Once the connection
is established, the unused transports are safely handled by the garbage
collector.
2026-03-03 14:22:43 +07:00
Cuong Manh Le
1f4c47318e refactor(config): consolidate transport setup and eliminate duplication
Consolidate DoH/DoH3/DoQ transport initialization into a single
SetupTransport method and introduce generic helper functions to eliminate
duplicated IP stack selection logic across transport getters.

This reduces code duplication by ~77 lines while maintaining the same
functionality.
2026-03-03 14:22:32 +07:00
Cuong Manh Le
e8d1a4604e perf(doq): implement connection pooling for improved performance
Implement QUIC connection pooling for DoQ resolver to match DoH3
performance. Previously, DoQ created a new QUIC connection for every
DNS query, incurring significant handshake overhead. Now connections are
reused across queries, eliminating this overhead for subsequent requests.

The implementation follows the same pattern as DoH3, using parallel dialing
and connection pooling to achieve comparable performance characteristics.
2026-03-03 14:22:16 +07:00
Cuong Manh Le
8d63a755ba Removing outdated netlink codes 2026-03-03 14:21:46 +07:00
Cuong Manh Le
f05519d1c8 refactor(network): consolidate network change monitoring
Remove separate watchLinkState function and integrate link state change
handling directly into monitorNetworkChanges. This consolidates network
monitoring logic into a single place and simplifies the codebase.

Update netlink dependency from v1.2.1-beta.2 to v1.3.1 and netns from
v0.0.4 to v0.0.5 to use stable versions.
2026-03-03 14:21:27 +07:00
Cuong Manh Le
1804e6db67 fix(windows): improve DNS server discovery for domain-joined machines
Add DNS suffix matching for non-physical adapters when domain-joined.
This allows interfaces with matching DNS suffix to be considered valid
even if not in validInterfacesMap, improving DNS server discovery for
remote VPN scenarios.

While at it, also replacing context.Background() with proper ctx
parameter throughout the function for consistent context propagation.
2026-03-03 14:20:14 +07:00
Cuong Manh Le
d0341497d1 Merge pull request #276 from Control-D-Inc/release-branch-v1.4.9
Release branch v1.4.9
v1.4.9
2026-01-13 21:41:48 +07:00
Cuong Manh Le
27c5be43c2 fix(system): disable ghw warnings to reduce log noise
Disable warnings from ghw library when retrieving chassis information.
These warnings are undesirable but recoverable errors that emit unnecessary
log messages. Using WithDisableWarnings() suppresses them while maintaining
functionality.
2026-01-09 15:10:29 +07:00
Cuong Manh Le
3beffd0dc8 .github/workflows: temporary use actions/setup-go
Since WillAbides/setup-go-faster failed with macOS-latest.

See: https://github.com/WillAbides/setup-go-faster/issues/37
2025-12-18 17:10:43 +07:00
Cuong Manh Le
1f9c586444 docs: add documentation for runtime internal logging 2025-12-18 17:10:43 +07:00
Cuong Manh Le
a92e1ca024 Upgrade quic-go to v0.57.1 2025-12-18 17:10:43 +07:00
Cuong Manh Le
705df72110 fix: remove incorrect transport close on DoH3 error
Remove the transport Close() call from DoH3 error handling path.
The transport is shared and reused across requests, and closing it
on error would break subsequent requests. The transport lifecycle
is already properly managed by the http.Client and the finalizer
set in newDOH3Transport().
2025-12-18 17:10:43 +07:00
Cuong Manh Le
22122c45b2 Including system metadata when posting to utility API 2025-12-18 17:10:39 +07:00
Cuong Manh Le
57a9bb9fab Merge pull request #268 from Control-D-Inc/release-branch-v1.4.8
Release branch v1.4.8
v1.4.8
2025-12-02 21:39:38 +07:00
Cuong Manh Le
78ea2d6361 .github/workflows: upgrade staticcheck-action to v1.4.0
While at it, also bump go version to 1.24
2025-11-12 15:22:01 +07:00
Cuong Manh Le
df3cf7ef62 Upgrade quic-go to v0.56.0 2025-11-12 15:15:16 +07:00
Cuong Manh Le
80e652b8d9 fix: ensure log and cache flags are processed during reload
During reload operations, log and cache flags were not being processed,
which prevented runtime internal logs from working correctly. To fix this,
processLogAndCacheFlags was refactored to accept explicit viper and config
parameters instead of relying on global state, enabling it to be called
during reload with the new configuration. This ensures that log and cache
settings are properly applied when the service reloads its configuration.
2025-11-12 15:15:05 +07:00
Cuong Manh Le
091c7edb19 Fix: Filter root domain from search domains on Linux
Remove empty and root domain (".") entries from search domains list
to prevent systemd-resolved errors. This addresses the issue where
systemd doesn't allow root domain in search domains configuration.

The filtering ensures only valid search domains are passed to
systemd-resolved, preventing DNS operation failures.
2025-11-12 15:14:40 +07:00
Cuong Manh Le
6c550b1d74 Upgrade quic-go to v0.55.0
While at it, also bump required go version to 1.24
2025-11-12 15:14:26 +07:00
Cuong Manh Le
3ca559e5a4 Merge pull request #264 from Control-D-Inc/release-branch-v1.4.7
Release branch v1.4.7
v1.4.7
2025-10-07 01:02:39 +07:00
Cuong Manh Le
0e3f764299 feat: add --rfc1918 flag for explicit LAN client support
Make RFC1918 listener spawning opt-in via --rfc1918 flag instead of automatic behavior.
This allows users to explicitly control when ctrld listens on private network addresses
to receive DNS queries from LAN clients, improving security and configurability.

Refactor network interface detection to better distinguish between physical and virtual
interfaces, ensuring only real hardware interfaces are used for RFC1918 address binding.
2025-09-25 16:45:56 +07:00
Cuong Manh Le
e52402eb0c Upgrade quic-go to v0.54.0 2025-09-25 16:45:05 +07:00
Cuong Manh Le
2133f31854 docs: add known issues documentation for Darwin 15.5 upgrade issue
Documents the self-upgrade issue on macOS Darwin 15.5 affecting
ctrld v1.4.2+ and provides workarounds for affected users.
2025-09-25 16:44:54 +07:00
Ginder Singh
a198a5cd65 start mobile library with provision id and custom hostname. 2025-09-25 16:44:39 +07:00
Cuong Manh Le
eb2b231bd2 Merge pull request #254 from Control-D-Inc/release-branch-v1.4.6
Release branch v1.4.6
v1.4.6
2025-08-22 04:08:56 +07:00
Jared Quick
7af29cfbc0 Add OPNsense new lease file
Signed-off-by: Jared Quick <jared.quick@salesforce.com>
2025-08-20 18:19:35 +07:00
Cuong Manh Le
ce1a165348 .github/workflows: bump go version to 1.24.x 2025-08-15 23:33:23 +07:00
Cuong Manh Le
fd48e6d795 fix: ensure upstream health checks can handle large DNS responses
- Add UpstreamConfig.VerifyMsg() method with proper EDNS0 support
- Replace hardcoded DNS messages in health checks with standardized verification method
- Set EDNS0 buffer size to 4096 bytes to handle large DNS responses
- Add test case for legacy resolver with extensive extra sections
2025-08-15 22:55:47 +07:00
Cuong Manh Le
d71d1341b6 refactor(prog): move network monitoring outside listener loop
Move the network monitoring goroutine initialization outside the listener
loop to prevent it from being started multiple times. Previously, the
network monitoring was started once per listener during first run, which
was unnecessary and could lead to multiple monitoring instances.

The change ensures network monitoring is started only once per program
execution cycle, improving efficiency and preventing potential resource
waste from duplicate monitoring goroutines.

- Extract network monitoring goroutine from listener loop
- Start network monitoring once per run cycle instead of per listener
- Maintain same functionality while improving resource usage
2025-08-12 16:49:05 +07:00
Cuong Manh Le
21855df4af fix: correct Windows API constants to fix domain join detection
The function was incorrectly identifying domain-joined status due to wrong
constant values, potentially causing false negatives for domain-joined machines.
2025-08-12 16:48:10 +07:00
Cuong Manh Le
66e2d3a40a refactor: move network monitoring to separate goroutine
- Move network monitoring initialization out of serveDNS() function
- Start network monitoring in a separate goroutine during program startup
- Remove context parameter from monitorNetworkChanges() as it's not used
- Simplify serveDNS() function signature by removing unused context parameter
- Ensure network monitoring starts only once during initial run, not on reload

This change improves separation of concerns by isolating network monitoring
from DNS serving logic, and prevents potential issues with multiple
monitoring goroutines if starting multiple listeners.
2025-08-12 16:46:57 +07:00
Cuong Manh Le
26257cf24a Merge pull request #250 from Control-D-Inc/release-branch-v1.4.5
Release branch v1.4.5
v1.4.5
2025-07-25 04:06:24 +07:00
Cuong Manh Le
36a7423634 refactor: extract empty string filtering to reusable function
- Add filterEmptyStrings utility function for consistent string filtering
- Replace inline slices.DeleteFunc calls with filterEmptyStrings
- Apply filtering to osArgs in addition to command args
- Improves code readability and reduces duplication
- Uses slices.DeleteFunc internally for efficient filtering
2025-07-15 23:09:54 +07:00
Cuong Manh Le
e616091249 cmd/cli: ignore empty positional argument for start command
The validation was added during v1.4.0 release, but causing one-liner
install failed unexpectedly.
2025-07-15 21:57:36 +07:00
Cuong Manh Le
0948161529 Avoiding Windows runners file locking issue 2025-07-15 20:59:57 +07:00
Cuong Manh Le
ce29b5d217 refactor: split selfUpgradeCheck into version check and upgrade execution
- Move version checking logic to shouldUpgrade for testability
- Move upgrade command execution to performUpgrade
- selfUpgradeCheck now composes these two for clarity
- Update and expand tests: focus on logic, not side effects
- Improves maintainability, testability, and separation of concerns
2025-07-15 19:12:23 +07:00
Cuong Manh Le
de24fa293e internal/router: support Ubios 4.3+
This change improves compatibility with newer UniFi OS versions while
maintaining backward compatibility with UniFi OS 4.2 and earlier.
The refactoring also reduces code duplication and improves maintainability
by centralizing dnsmasq configuration path logic.
2025-07-15 19:11:13 +07:00
Cuong Manh Le
6663925c4d internal/router: support Merlin Guest Network Pro VLAN
By looking for any additional dnsmasq configuration files under
/tmp/etc, and handling them like default one.
2025-07-15 19:10:10 +07:00