End-of-day snapshot. Everything below was verified live on a physical iPhone 17 (iOS 26.4.2) with the VPN active, browsing real sites in Safari.
Status: working as expected
- DNS forwarding (UDP/53 → NWConnection → response packet back to TUN): healthy.
- TCP forwarding (userspace state machine, MSS segmentation, FIN bookkeeping centralised in
send()): healthy. No SYN-replay races (per-flowepochtoken), no half-open leaks (idle eviction sweep at 90 s). - TLS SNI extraction: now works on any port —
dns.google(DoT 853),*.push.apple.com(5223), IMAPS (993), etc. resolve to hostnames in the Network tab. - HTTPS MITM decryption: working end-to-end on
busymate.io,busydrivers.com,portal.busydrivers.app. Cert generation hits the per-host cache after the first request; concurrent sessions for the same host start in <1 ms. - Per-pair HTTP/1.1 framing (
HTTP1MessageParser): traffic-log entries land in the in-app Network tab in real time. No more 2-minute keep-alive parking. Verified on multi-request keep-alive connections. - ALPN stop-gap:
http/1.1advertised on both MITM TLS legs so upstream falls back to HTTP/1.1; status codes parse correctly (200/304/400/404/204all observed). - Log rotation:
traffic.jsonlcapped 10/5 MB,diagnostics.log5/2.5 MB, truncation lands at the next newline so JSONL stays parseable. - Incremental polling: single
seek+readToEndper tick (4 Hz), no full-file decode. - CA private key (
ca.key) now written with.completeFileProtectionUntilFirstUserAuthentication.
Configuration
- App Group:
group.com.busymatehelper - Main app bundle ID:
com.busymatehelper.app - Extension bundle ID:
com.busymatehelper.app.tunnel - SSL proxy domain list (managed in Settings tab):
busymate.io,busydrivers.com,portal.busydrivers.app
Repo layout (as of today)
Today's commits (in order)
| Commit | Summary |
|---|---|
a343e0c | Rename BusymateVPN → BusymateHelper; tighten bundle IDs |
deb5778 | Restructure monorepo: ios/, web/, docs/ |
b62e5b8 | Apply audit Tier 1 fixes (10 items) |
8b241c9 | Apply audit Tier 2 fixes (6 items) |
e2b29d6 | SNI buffering: fall back early on complete-but-unparseable records |
9bee201 | ALPN http/1.1 stop-gap on MITM TLS legs |
6c62558 | Tier 3 #2: per-request HTTP/1.1 framing in MITMSession |
db95a53 | Fix HTTP1MessageParser crash on Data subscript with non-zero startIndex |
1dd4ad1 | Audit polish: Y2050 DER, UInt64 session IDs, surface log-write errors |
18ac2c1 | sniffTraffic: extract SNI on any TLS port (not just 443) |
6e609ce | Update architecture doc + monorepo blurb |
83f2f1d | Audit #13: dedupe TrafficLogEntry via shared synchronized group |
Audit close-out
23 of 24 items shipped. Only remaining item:
- HTTP/2 framer + HPACK decoder — would let MITM speak HTTP/2 to upstream and remove the
http/1.1-only ALPN constraint. Multi-hour, only needed if/when there's a need to inspect h2-only servers' wire frames.
Plus one cosmetic-only nit untouched: indent glitch at ios/PacketTunnelExtension/PacketTunnelProvider.swift:126.
Known gaps (separate from the audit)
- UDP/443 (QUIC / HTTP/3) is silently dropped at
inspectPacket. Modern Safari tries HTTP/3 first and falls back to TCP/443 after a short timeout. This adds latency on first request to QUIC-preferring origins. - Network-tab entries for long-lived non-MITM connections (APNs, DoT) appear only when the connection closes (FIN/RST/eviction). Persistent connections that stay open for hours won't show until the tunnel stops.
- The shared-group
Shared/synced root group is a relatively new Xcode feature. If anyone opens the project in older Xcode, the dedup may not be honoured.