The build stage ran on the target platform, so a multi-platform build
ran the Go toolchain under qemu. On hosts with an older qemu-user
(Ubuntu 22.04 ships 6.2) Go crashed building linux/arm/v7, and the
image still built: scripts/build.sh did not fail on a build error, and
the COPY of ctrld-linux-*-nocgo matched nothing, so the image shipped
without ctrld.
In both docker/Dockerfile and docker/Dockerfile.debug, run the build
stage on BUILDPLATFORM and cross-compile for the target with
scripts/build.sh linux/amd64, linux/arm64 or linux/armv7. Then move
the binary built for that target, by its exact name, to a fixed path,
and fail when it is missing. scripts/build.sh now exits non-zero when
go generate or go build fails, and .dockerignore keeps ctrld-* files
from the host out of the build context, so a leftover binary can never
stand in for a failed build. Drop the outdated CTRLD_NO_QF variable.
macOS intercept mode fails totally on networks that provide no usable
IPv4 DNS (e.g. IPv6-only iPhone tethering with 464XLAT): the pf ruleset
blocks all outbound IPv6 port 53, and with no IPv4 DNS configured
mDNSResponder emits no DNS packets at all, so pf has nothing to
intercept while the Control D upstream stays provably healthy.
When network-change recovery discovers no usable IPv4 DNS on the
default-route service, set 127.0.0.1 as that service DNS so macOS can
emit queries that land directly on the listener. The entry is removed
when the network regains IPv4 DNS and on intercept shutdown; networks
that provide IPv4 DNS are never modified. Runs on the already-debounced
recovery path so interface flaps do not churn networksetup.
Also fix the canceled-recovery state leak: the cancellation early
return never reset recoveryBypass/recoveryRunning, so a flap burst
ending in a canceled recovery left the daemon in bypass forever with
the DNS watchdog disabled. Cleanup is generation-gated so a superseded
recovery never clears state owned by its successor.
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).
Since go1.21, Go standard library have added support for QUIC protocol.
The binary size gains between quic and quic-free version is now minimal.
Removing the quic free build, simplify the code and build process.