Fixes: admin/mini-sing#1
gVisor TUN stack intercepts ICMP echo requests and replies locally
with fake <1ms latency. Real pings to Tailscale peers never reach
the WireGuard tunnel.
Fix: PrepareConnection now checks ICMP destinations against route
rules. If the matching outbound implements ICMPPinger (e.g. Tailscale),
returns an icmpProxy DirectRouteDestination that:
1. Sends the ICMP echo through tailnet's netstack via DialPing("ping4")
2. Reads the real reply from the WireGuard tunnel
3. Rebuilds a raw IP+ICMP reply packet
4. Writes it back to the TUN via DirectRouteContext
Changes:
- adapter/outbound.go: Add ICMPPinger interface
- adapter/router.go: Add FindOutbound to ConnectionRouterEx
- route/router.go: Expose FindOutbound method
- protocol/tailscale/outbound.go: Implement ICMPPinger via tailnet.DialPing
- protocol/tun/inbound.go: ICMP proxy in PrepareConnection + icmpProxy type
- tailnet/outbound.go: Add DialPing method (wraps tnet.DialContext("ping4"))
- Use atomic.Bool for started flag to prevent data race between
async srv.Up() goroutine and DialContext/LookupTailscale callers.
- Read and store AcceptRoutes from options (was declared but unused).
- Cache LookupTailscale peer status for 30s to avoid per-query API calls.
- Remove .local from DNS intercept — it's mDNS reserved (RFC 6762),
not Tailscale-specific. Only intercept .ts.net.
- Move detectDefaultInterface/makeBindToDeviceFunc to box_linux.go
with no-op stubs in box_other.go (fixes macOS/Android build)
- Enable PreferIPv4 in DNS resolver config
- Reduce protect() log verbosity: only log failures, not every call
- Detect TUN inbound and bind direct sockets to physical interface
via SO_BINDTODEVICE, preventing DNS upstream traffic from looping
through TUN
- Exclude direct DNS upstream IPs from TUN routing table
- Resolver exposes DirectUpstreamAddrs() for TUN route exclusion
- Support multi-upstream DNS config with concurrent query groups
- Store resolver in Box struct, close on shutdown (prevents socket/goroutine leak)
- Add Resolver.Close() method
- Fix detour closure capturing loop variable (all detours pointed to last outbound)
- Default DNS fallback when no servers configured (223.5.5.5 + 8.8.8.8:853)
- Redact Tailscale auth keys and VLESS credentials from test configs
Multi-protocol proxy client (shadowsocks, vmess, vless, trojan) with
TUN support and integrated DNS powered by mini-dns.
DNS features via mini-dns:
- Split routing: CN domains → local DNS, foreign → remote DNS
- Multi-upstream concurrent queries per group
- Remote DNS routed through proxy outbound nodes (DialFunc injection)
- Pollution filtering, TTL cache with prefetch/serve-stale
- Optional DNS listener (UDP/TCP) alongside embedded Exchange() API