You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Listen directly on interface IP:53 for DNS, add debug logging
- DNS forwarder now binds to the gateway interface IP on port 53
instead of requiring pf to redirect DNS traffic
- Add --dns flag for easy enablement with auto-detection of interface IP
- Add --interface flag to specify network interface (default: en0)
- Add info-level logging for proxy connections and DNS responses
- Add debug-level logging for DNS queries, SNI, and tunnel details
- Default log level is debug in debug builds, info in release builds
- Compile out debug logs in release builds via release_max_level_info
- Print log level at startup
- Remove DNS redirect from pf setup script
- Add DNS forwarder integration test
- Bump version to 0.3.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+36-40Lines changed: 36 additions & 40 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,7 +18,7 @@ Designed to run on a Mac acting as a side router (gateway) for other devices on
18
18
19
19
-**pf integration** — Uses `DIOCNATLOOK` ioctl on `/dev/pf` to recover original destinations from pf's NAT state table
20
20
-**SNI extraction** — Peeks at TLS ClientHello to extract hostnames, sending proper `CONNECT host:port` instead of raw IPs
21
-
-**DNS interception** — Optional local DNS forwarder that builds an IP→domain lookup table as a fallback for hostname resolution (supports both traditional UDP and DNS-over-HTTPS)
21
+
-**DNS forwarder** — Listens directly on the gateway interface (port 53) for LAN client DNS queries, building an IP→domain lookup table. Supports DNS-over-HTTPS (DoH) and traditional UDP upstream.
22
22
-**Anchor-based pf rules** — Won't clobber your existing firewall config
23
23
-**Daemon mode** — Run as a background process with PID file and log file support
24
24
-**Async I/O** — Built on tokio with per-connection task spawning
@@ -27,7 +27,7 @@ Designed to run on a Mac acting as a side router (gateway) for other devices on
27
27
28
28
- macOS 12+ (uses pf and `DIOCNATLOOK` ioctl)
29
29
- Rust 1.70+ and Cargo
30
-
- Root privileges (for `/dev/pf` access and pf rule management)
30
+
- Root privileges (for `/dev/pf` access and port 53 binding)
31
31
- An upstream HTTP CONNECT proxy (e.g., Squid, mitmproxy, or any CONNECT-capable proxy)
32
32
33
33
## Build
@@ -57,19 +57,18 @@ cargo test
57
57
This example assumes your upstream HTTP proxy runs on `127.0.0.1:1082` and your LAN interface is `en0`.
58
58
59
59
```bash
60
-
# Step 1: Start the transparent proxy with DNS interception (DoH by default)
60
+
# Step 1: Start the transparent proxy with DNS on the gateway interface
61
61
sudo ./target/release/trans_proxy \
62
62
--upstream-proxy 127.0.0.1:1082 \
63
-
--dns-listen 0.0.0.0:5353
63
+
--dns
64
64
65
65
# Or run as a daemon
66
66
sudo ./target/release/trans_proxy \
67
67
--upstream-proxy 127.0.0.1:1082 \
68
-
--dns-listen 0.0.0.0:5353 \
69
-
-d
68
+
--dns -d
70
69
71
70
# Step 2: Set up pf redirection (in another terminal, or same if using -d)
72
-
sudo scripts/pf_setup.sh en0 8443 5353
71
+
sudo scripts/pf_setup.sh en0 8443
73
72
74
73
# Step 3: Configure client devices (see "Client Setup" below)
@@ -246,7 +242,7 @@ Settings → Wi-Fi → Long press network → Modify → Advanced → IP setting
246
242
The proxy resolves hostnames for CONNECT requests using a fallback chain:
247
243
248
244
1.**SNI extraction** — Parses the TLS ClientHello to read the Server Name Indication extension (port 443 only). No TLS termination or certificate generation required.
249
-
2.**DNS table lookup** — If `--dns-listen` is enabled, the built-in DNS forwarder records IP→domain mappings from A record responses. Works for both HTTP (port 80) and HTTPS (port 443).
245
+
2.**DNS table lookup** — If `--dns` is enabled, the built-in DNS forwarder records IP→domain mappings from A record responses. Works for both HTTP (port 80) and HTTPS (port 443).
250
246
3.**Raw IP** — Falls back to the IP address if no hostname can be determined.
251
247
252
248
### Why DIOCNATLOOK?
@@ -272,9 +268,9 @@ This is a harmless warning from `pfctl`. macOS doesn't include ALTQ — pf redir
272
268
- Ensure IP forwarding is enabled: `sysctl net.inet.ip.forwarding` (should be `1`)
273
269
274
270
### DNS not resolving on client devices
275
-
- Ensure `--dns-listen` is set and the DNS forwarder is running
276
-
-Ensure pf is redirecting port 53: `sudo pfctl -a trans_proxy -s rules`
277
-
- Test: `dig @<gateway_ip> -p 5353 example.com`
271
+
- Ensure `--dns` is set and the DNS forwarder is running
272
+
-Check that trans_proxy logs show `DNS forwarder listening on <ip>:53`
<p>Peeks at the TLS ClientHello to extract hostnames, sending proper <code>CONNECT host:port</code> instead of raw IPs. No TLS termination or certificate generation needed.</p>
832
832
</div>
833
833
<divclass="feature">
834
-
<h3>DNS Interception</h3>
835
-
<p>Optional local DNS forwarder that captures A record responses and builds an IP→domain lookup table. Supports DNS-over-HTTPS (DoH) and traditional UDP upstream.</p>
834
+
<h3>DNS Forwarder</h3>
835
+
<p>Listens directly on the gateway interface (port 53) for LAN client DNS queries. Builds an IP→domain lookup table. Supports DoH and UDP upstream.</p>
836
836
</div>
837
837
<divclass="feature">
838
838
<h3>Safe pf Anchors</h3>
@@ -891,26 +891,22 @@ <h2>Quick Start</h2>
891
891
<divclass="steps">
892
892
<divclass="step">
893
893
<h3>Start the transparent proxy</h3>
894
-
<p>Run with DNS interception enabled (uses Cloudflare DoH by default):</p>
0 commit comments