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
+5
View File
@@ -90,6 +90,11 @@ func (e *LogEvent) Int64(key string, val int64) *LogEvent {
return e
}
func (e *LogEvent) Uint64(key string, val uint64) *LogEvent {
e.fields = append(e.fields, zap.Uint64(key, val))
return e
}
// Err adds an error field to the event
func (e *LogEvent) Err(err error) *LogEvent {
if err != nil {