Files
WTFnet/docs/DNS_LEAK_DETECTOR_IMPLEMENTATION.md
2026-01-17 20:07:13 +08:00

4.7 KiB

DNS Leak Detector - Implementation Guide (v0.4)

This document explains how to implement the DNS leak detector as a new subcrate in WTFnet.

1) New crate: wtfnet-dnsleak

1.1 Module layout

crates/wtfnet-dnsleak/src/

  • lib.rs
  • policy.rs # safe path constraints + presets
  • sensor.rs # passive capture -> normalized TrafficEvent stream
  • classify.rs # transport classification + confidence
  • route.rs # interface/route classification (tunnel/physical/loopback)
  • rules.rs # Leak-A/B/C/D evaluation
  • report.rs # LeakEvent + SummaryReport builders
  • privacy.rs # full/redacted/minimal redaction logic

2) Core data types

2.1 TrafficEvent (raw from sensor)

Fields:

  • ts: timestamp
  • proto: udp/tcp
  • src_ip, src_port
  • dst_ip, dst_port
  • iface_name (capture interface if known)
  • payload: optional bytes (only for plaintext DNS parsing)

2.2 ClassifiedEvent

Adds:

  • transport: udp53/tcp53/dot/doh/unknown
  • doh_confidence: HIGH/MEDIUM/LOW (only if doh)
  • qname/qtype: nullable

2.3 EnrichedEvent

Adds:

  • route_class: loopback/tunnel/physical/unknown
  • process info: pid/ppid/name (nullable)
  • attribution_confidence: HIGH/MEDIUM/LOW/NONE
  • attrib_failure_reason: optional string

2.4 LeakEvent (final output)

Adds:

  • leak_type: A/B/C/D
  • severity: P0..P3
  • policy_rule_id
  • evidence: minimal structured evidence

3) Platform integration: Process Attribution Engine (PAE)

3.1 Trait addition (wtfnet-platform)

Add: trait FlowOwnerProvider { fn owner_of( &self, proto: Proto, src_ip: IpAddr, src_port: u16, dst_ip: IpAddr, dst_port: u16, ) -> FlowOwnerResult; }

FlowOwnerResult:

  • pid, ppid, process_name (optional)
  • confidence: HIGH/MEDIUM/LOW/NONE
  • failure_reason: optional string

Design rule: attribution is best-effort and never blocks leak detection.

4) Transport classification logic

4.1 Plain DNS

Match:

  • UDP dst port 53 OR TCP dst port 53 Parse QNAME/QTYPE from payload.

4.2 DoT

Match:

  • TCP dst port 853

4.3 DoH (heuristic)

Match candidates:

  • TCP dst port 443 AND (one of):
    • dst IP in configured DoH resolver list
    • dst SNI matches known DoH provider list (if available)
    • frequent small HTTPS bursts pattern (weak)

Attach confidence:

  • MEDIUM: known endpoint match
  • LOW: traffic-shape heuristic only

5) Policy model

Policy defines "safe DNS path" constraints:

  • allowed interfaces
  • allowed destinations (IP/CIDR)
  • allowed processes
  • allowed ports

A DNS event is a leak if it violates safe-path constraints.

5.1 Built-in profiles

full-tunnel:

  • allow DNS only via tunnel iface or loopback stub
  • any UDP/TCP 53 on physical iface => Leak-A

proxy-stub (default):

  • allow DNS only to loopback stub
  • allow stub upstream only to proxy destinations
  • flag direct DoH/DoT outside proxy path => Leak-C

split:

  • allow plaintext DNS only for allowlist
  • enforce unknown => proxy resolve (Leak-B)

6) Leak rules (A/B/C/D)

Leak-A (plaintext escape):

  • transport udp53/tcp53
  • route_class != allowed
  • dst not in allowed destination set

Leak-B (split policy intent leak):

  • qname matches proxy-required set or "unknown"
  • query observed going to ISP/domicile resolver or non-tunnel iface

Leak-C (encrypted bypass):

  • DoT or DoH flow exists
  • not via approved egress path (iface/destination)

Leak-D (mismatch indicator):

  • correlate qname to later TCP/TLS flows (optional v0.4 NICE)

7) Privacy modes

Because domains and cmdlines are sensitive, support:

  • Full: store full qname and cmdline
  • Redacted (default): hash qname or keep eTLD+1 only; truncate cmdline
  • Minimal: no domains/cmdline; keep leak counts + resolver IPs + process name

Privacy mode applies in report builder, not in sensor.

8) CLI integration

Add under dns command group:

  • dns leak status
  • dns leak watch
  • dns leak report

watch returns:

  • summary report (human) by default
  • --json returns structured report with events list

--follow keeps the watch running by resolving the duration to a large placeholder (one year in milliseconds) and then racing the watch against tokio::signal::ctrl_c(); Ctrl-C returns early with a clean exit code so the outer loop stops.

Phase 1 (core passive detection):

  • sensor: udp/tcp capture
  • classify: udp53/tcp53/dot
  • parse plaintext qname/qtype
  • policy: allowlist + allowed interfaces/dests
  • leak rules: Leak-A + Leak-C (DoT)
  • report: events + summary

Phase 2 (process attribution + DoH heuristics):

  • platform FlowOwnerProvider impls
  • DoH heuristic classification + confidence
  • privacy modes

Phase 3 (optional correlation / Leak-D):

  • flow tracker correlating DNS -> TCP/TLS connect events
  • mismatch indicator output