What's New
🚀 Bind-Interface Support
- New
--bind <iface>flag onhttp,cfscanner, andproxycommands - Pins outbound dials to a specific OS interface (e.g.
eth0) — useful when the host has multiple paths and you want to bypass a VPN tunnel for the proxy itself - Implemented at every layer: raw scanner dials, xray-core (via
internet.RegisterDialerController), sing-box (viaRouteOptions.DefaultInterface) - Cross-platform:
SO_BINDTOIFINDEX→SO_BINDTODEVICEon Linux,IP_BOUND_IFon Darwin,IP_UNICAST_IFon Windows - Interface existence is validated up front — a typo fails fast instead of silently doing nothing
🌐 Configurable Tunnel DNS (App Mode)
--dns <server>lets you pick the resolver used inside the app-mode tunnel (default1.1.1.1)--dns-type {udp,tcp,tls,https}picks the transport (defaultudp— changed from the previous TCP default since TCP/53 is often blocked at exit proxies)- HTTPS form supports full URL:
--dns-type https --dns https://1.1.1.1/dns-query - Bad values rejected at tunnel start with a clear error
🔌 cfscanner Custom Ports
- New
--portflag (default443) for scanning Cloudflare's alternate TLS ports —2053,2083,2087,2096,8443 - Useful when 443 is filtered by the local network
🛡️ Proxy App-Mode Hardening
- Concurrent
proxy --mode appinvocations no longer clobber each other — veth names are now PID-suffixed and the on-disk state file stamps PID + boot_id RecoverFromCrashchecks the owning PID is actually dead before reclaiming resources- State file writes are atomic (tmp + rename)
- TUN device teardown is now awaited before the namespace is deleted (no more "device busy" warnings)
🔗 Proxy Chaining (Multi-Hop)
- New
--chainflag chains multiple outbound configs into a single circuit --chain-links/--chain-filefor fixed chains,--chain-hopsfor random selection from pool--chain-rotation {none,exit,full}controls how rotation interacts with chains
🔄 Upstream Updates
- xray-core:
v1.260123.0→v1.260327.0(latest) - Minimum Go 1.26 (auto-toolchain bump driven by xray-core)
- Migrated
TLSConfig.Insecure→AllowInsecure(xray-core rename; old field becomes a hard error after 2026-06-01 upstream) - sing-box
InboundOptions.Sniff*migrated to asniffroute rule action (deprecated fields are removed in sing-box 1.13 final)
🐛 Bug Fixes
- App-mode routing loop:
AutoDetectInterface=trueinside the namespace was resolving the "default interface" to the TUN itself, causing the SOCKS dialer to loop back into gvisor. SOCKS dialer is now pinned to the veth, and the upstream proxy IP is added toRouteExcludeAddress - OS-thread leak:
StartTunnelno longer hands a thread that briefly entered the target netns back to the Go scheduler — the tunnel goroutine now owns its OS thread for life - Trojan parser: removed bogus
"method": "chacha20"and"ota": falsefields that were copy-paste leftovers from shadowsocks; these aren't part of xray-core'sTrojanServerTargetschema - VLESS parser: removed dead
"alterId": 0field (VLESS has noalterId) - JSON-injection hardening: replaced
fmt.SprintfJSON templates withjson.Marshalover typed maps for vless / vmess / trojan, so passwords or UUIDs containing quotes can no longer corrupt the emitted config - WireGuard test: bracketed bare IPv6 host that Go 1.26's stricter
url.Parsewas rejecting - Cleanup order: tunnel
Closeerrors are now captured and logged; cleanup waits for the TUN device to disappear before deleting the namespace - Privilege check in
proxy.New()was running aftersysproxy.LoadStateandRecoverFromCrash— hoisted to the top so non-root invocations fail fast without side effects
⚡ Improvements
- Single OS-thread guard around
RegisterDialerControllerso repeated core construction in the same process doesn't stack bind hooks core.FactoryOptionsstruct gives callers a backward-compatible way to pass new core options without breakingCoreFactory(coreType, insecure, verbose)callers- DNS transport registration is now lazy — only the configured
--dns-typetransport is registered at tunnel start
Note for app-mode users: the upstream config link's hostname (the proxy server itself) is still resolved by the host's stdlib resolver. The new --dns flags only affect DNS for apps running inside the namespace.