dns_intercept: add WFP loopback protect for VPN block-outside-dns

When third-party VPN software (e.g., OpenVPN) installs WFP block filters via
block-outside-dns, all DNS traffic to non-tunnel interfaces is blocked —
including DNS to 127.0.0.1 (ctrld's NRPT target). This breaks DNS mode
interception because the NRPT catch-all rule routes queries to loopback,
but WFP blocks the connection before it reaches ctrld's listener.

Fix: after exhausting all NRPT recovery attempts, activate a minimal WFP
session with "hard permit" filters (FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT)
for DNS to localhost in a max-priority sublayer (weight 0xFFFF). This
overrides the VPN's block for loopback DNS only, while preserving the
VPN's DNS leak protection for all other (non-loopback) DNS traffic.

The loopback protect is:
- Only activated when NRPT probes fail (not preemptively)
- Harmless when no conflicting WFP blocks exist (permit-only, no blocks)
- Persistent until ctrld shutdown (survives VPN reconnect cycles)
- Cleaned up by the existing cleanupWFPFilters path on shutdown
This commit is contained in:
Codescribe
2026-04-29 04:42:12 -04:00
committed by Cuong Manh Le
parent 8abeeea4c3
commit 81aa6b237b
6 changed files with 336 additions and 32 deletions
+1 -1
View File
@@ -338,7 +338,7 @@ func (p *prog) initLogging(backup bool) {
// internalLogFilePath returns the path for persisted internal logs.
// The file lives in the ctrld home directory alongside other runtime state.
func internalLogFilePath() string {
return absHomeDir(logFileName)
return ctrld.AbsHomeDir(logFileName)
}
// initInternalLogging performs internal logging if there's no log enabled.