feat: support Windows TUN mode - #102
kitty-eu-org wants to merge 5 commits into
Conversation
|
Has there been any progress on this issue? |
cfal
left a comment
There was a problem hiding this comment.
i think this PR was mainly written by AI without quite understanding the consequences - and i can't tell whether the tun changes are correct and if they break anything on Linux which was just recently fixed. I'm curious if the entire event loop in run_tun_server actually needs to be changed to support Windows.
There was a problem hiding this comment.
The tun-rs library now supports asynchronous mode, so I want to convert all the code to be uniformly asynchronous. Additionally, Windows does not support file descriptors (fd), so I implemented a VirtTunDeviceand channel by referring to the implementation in shadowsocks-rust. This unavoidably leads to substantial changes to your original code.
I have indeed used AI to write a lot of code, but I have tested it on Windows and confirmed that tun works properly. It has also been tested on Linux and works correctly |
The control API landed, so the roadmap gains a section for what it was the first step of: seven sub-projects, one merged and six open, in roughly the order they unblock each other. Recorded there rather than only in the spec, because two of them are decisions someone will otherwise make twice. Windows TUN does not exist -- src/lib.rs gates the module on cfg(unix), so run_prepared returns Unsupported and a Windows GUI would fail at the Connect button -- and upstream PR cfal#102, which implements it, is not adoptable: it converts the stack to AsyncDevice, deleting the dedicated-thread design MOBILE.md's tuning rests on, and removes the dead-descriptor guard at tcp_stack_direct.rs:620. macOS, by contrast, needs no new Rust at all. Also notes that shoes deliberately configures no host routes or DNS, so each privileged helper owns that -- four different mechanisms on Linux -- and updates Tier 2 #6: the live connection count shipped, and the rest is blocked on outbounds having no name to key per-server bytes on.
The control API landed, so the roadmap gains a section for what it was the first step of: seven sub-projects, one merged and six open, in roughly the order they unblock each other. Recorded there rather than only in the spec, because two of them are decisions someone will otherwise make twice. Windows TUN does not exist -- src/lib.rs gates the module on cfg(unix), so run_prepared returns Unsupported and a Windows GUI would fail at the Connect button -- and upstream PR cfal#102, which implements it, is not adoptable: it converts the stack to AsyncDevice, deleting the dedicated-thread design MOBILE.md's tuning rests on, and removes the dead-descriptor guard at tcp_stack_direct.rs:620. macOS, by contrast, needs no new Rust at all. Also notes that shoes deliberately configures no host routes or DNS, so each privileged helper owns that -- four different mechanisms on Linux -- and updates Tier 2 #6: the live connection count shipped, and the rest is blocked on outbounds having no name to key per-server bytes on.
The smoltcp loop moves from tcp_stack_direct.rs to stack_common.rs behind a StackDevice trait and a shared StackHandle manager, unchanged in behaviour; the Unix backend keeps its descriptor and poll(), and tcp_stack_wintun.rs drives a wintun ring-buffer session - dedicated thread, batching and the dead-device backstop preserved - waiting on the session's event handles and woken at shutdown through Session::shutdown(), the way wireguard-go does it. shoes creates and configures the adapter itself (wintun_device.rs): deterministic GUID per name so Windows reuses one network profile, ring sized as wireguard-go's, and wintun.dll's signature verified before it is loaded. Routes and DNS stay the host's: `destination` is refused on Windows because the wintun configuration path would turn it into a system default route, and the adapter address must be IPv4 because wintun-bindings' netsh arm cannot express IPv6. Upstream PR cfal#102 was read for which knobs matter and deliberately not adopted - it deletes the dedicated-thread design and the busy-loop backstop, both kept here. Making the full test suite run on Windows (the CI job was check-only) surfaced two pre-existing Windows defects, both fixed: QUIC inbounds panicked at startup on SO_REUSEPORT, which does not exist there - they now bind one endpoint and say so when reducing a configured num_endpoints - and the hysteria2/TUIC UDP relays lost all their IPv4 traffic because Windows defaults IPV6_V6ONLY on where Linux defaults it off; dual-stack sockets now request it explicitly. A live end-to-end run on Windows 11 (fake-IP DNS in 6-12 ms, TLS with SNI restored from the fake address, 20 MB at ~35 MB/s, UDP relay, ICMP, clean teardown) then caught two defects that were never Windows-specific, fixed everywhere: a UDP response queued while the stack thread was idle waited out the 1 s poll timeout because nothing woke the thread on enqueue - the response path now carries a waker, a byte down the wake pipe on Unix and an auto-reset event in the Windows wait - and icmp_enabled never actually answered pings, because smoltcp's echo replies sit behind its auto-icmp-echo-reply feature, now enabled. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Added TUN mode support for Windows to enable transparent proxying. This implementation covers interface creation and basic routing setup.