Refactor: Fully overhaul TUN mode architecture. Replace stub with auto-downloading Go tun2socks daemon, inject dynamic Windows PowerShell routing tables with proxy IP exclusions, metrics and secure DNS resolver, and prune legacy wintun crate bindings.

This commit is contained in:
ospab 2026-05-15 00:35:25 +03:00
parent 292ba3b3d7
commit 0b3ee775e4
6 changed files with 198 additions and 229 deletions

182
Cargo.lock generated
View File

@ -101,7 +101,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]
@ -134,26 +134,6 @@ version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "c2rust-bitfields"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b43c3f07ab0ef604fa6f595aa46ec2f8a22172c975e186f6f5bf9829a3b72c41"
dependencies = [
"c2rust-bitfields-derive",
]
[[package]]
name = "c2rust-bitfields-derive"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3cbc102e2597c9744c8bd8c15915d554300601c91a079430d309816b0912545"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "cesu8" name = "cesu8"
version = "1.1.0" version = "1.1.0"
@ -232,7 +212,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]
@ -309,7 +289,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]
@ -438,7 +418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
dependencies = [ dependencies = [
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]
@ -453,16 +433,6 @@ version = "0.2.185"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
[[package]]
name = "libloading"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
dependencies = [
"cfg-if",
"windows-link",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.29" version = "0.4.29"
@ -506,7 +476,7 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]] [[package]]
name = "ostp" name = "ostp"
version = "0.1.20" version = "0.1.21"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64", "base64",
@ -521,7 +491,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-client" name = "ostp-client"
version = "0.1.20" version = "0.1.21"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -532,12 +502,11 @@ dependencies = [
"serde_json", "serde_json",
"tokio", "tokio",
"tracing", "tracing",
"wintun",
] ]
[[package]] [[package]]
name = "ostp-core" name = "ostp-core"
version = "0.1.20" version = "0.1.21"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -569,7 +538,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-server" name = "ostp-server"
version = "0.1.20" version = "0.1.21"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -724,7 +693,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]
@ -799,17 +768,6 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.117" version = "2.0.117"
@ -838,7 +796,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]
@ -865,7 +823,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]
@ -887,7 +845,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]
@ -958,25 +916,6 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "windows"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-link" name = "windows-link"
version = "0.2.1" version = "0.2.1"
@ -989,7 +928,7 @@ version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [ dependencies = [
"windows-targets 0.42.2", "windows-targets",
] ]
[[package]] [[package]]
@ -1007,29 +946,13 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.42.2", "windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.2", "windows_aarch64_msvc",
"windows_i686_gnu 0.42.2", "windows_i686_gnu",
"windows_i686_msvc 0.42.2", "windows_i686_msvc",
"windows_x86_64_gnu 0.42.2", "windows_x86_64_gnu",
"windows_x86_64_gnullvm 0.42.2", "windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.42.2", "windows_x86_64_msvc",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
] ]
[[package]] [[package]]
@ -1038,103 +961,42 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "wintun"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b3c8c8876c686f8a2d6376999ac1c9a24c74d2968551c9394f7e89127783685"
dependencies = [
"c2rust-bitfields",
"libloading",
"log",
"thiserror",
"windows",
]
[[package]] [[package]]
name = "x25519-dalek" name = "x25519-dalek"
version = "2.0.1" version = "2.0.1"
@ -1164,7 +1026,7 @@ checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]
@ -1184,7 +1046,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.117", "syn",
] ]
[[package]] [[package]]

View File

@ -14,6 +14,3 @@ rand.workspace = true
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
portable-atomic.workspace = true portable-atomic.workspace = true
[target.'cfg(target_os = "windows")'.dependencies]
wintun = "0.4.0"

View File

@ -68,6 +68,7 @@ pub async fn run_client(config: crate::config::ClientConfig) -> Result<()> {
if config.mode == "tun" { if config.mode == "tun" {
tunnel::download_wintun_dll(config.debug)?; tunnel::download_wintun_dll(config.debug)?;
tunnel::download_tun2socks(config.debug)?;
} }
let (proxy_events_tx, proxy_events_rx) = mpsc::channel(10000); let (proxy_events_tx, proxy_events_rx) = mpsc::channel(10000);
@ -153,7 +154,7 @@ pub async fn run_client(config: crate::config::ClientConfig) -> Result<()> {
let wintun_shutdown_rx = shutdown_tx.subscribe(); let wintun_shutdown_rx = shutdown_tx.subscribe();
let wintun_task = if config_clone.mode == "tun" { let wintun_task = if config_clone.mode == "tun" {
Some(tokio::spawn(async move { Some(tokio::spawn(async move {
tunnel::run_wintun_tunnel(wintun_shutdown_rx, config_clone.debug).await tunnel::run_wintun_tunnel(config_clone, wintun_shutdown_rx).await
})) }))
} else { } else {
None None

View File

@ -3,6 +3,7 @@ mod wintun_downloader;
mod wintun_handler; mod wintun_handler;
pub use wintun_downloader::download_wintun_dll; pub use wintun_downloader::download_wintun_dll;
pub use wintun_downloader::download_tun2socks;
pub use wintun_handler::run_wintun_tunnel; pub use wintun_handler::run_wintun_tunnel;
use tokio::sync::{mpsc, watch}; use tokio::sync::{mpsc, watch};

View File

@ -47,3 +47,49 @@ pub fn download_wintun_dll(debug: bool) -> Result<()> {
pub fn download_wintun_dll(_debug: bool) -> Result<()> { pub fn download_wintun_dll(_debug: bool) -> Result<()> {
Ok(()) Ok(())
} }
#[cfg(target_os = "windows")]
pub fn download_tun2socks(debug: bool) -> Result<()> {
let exe = std::env::current_exe()?;
let dir = exe.parent().ok_or_else(|| anyhow!("failed to get binary directory"))?;
let tun2socks_path = dir.join("tun2socks.exe");
if !tun2socks_path.exists() {
if debug {
println!("[ostp-client] tun2socks.exe not found. Downloading automatically...");
}
let zip_path = dir.join("tun2socks.zip").to_string_lossy().replace('\\', "/");
let temp_path = dir.join("tun2socks_temp").to_string_lossy().replace('\\', "/");
let dest_path = tun2socks_path.to_string_lossy().replace('\\', "/");
let url = "https://github.com/xjasonlyu/tun2socks/releases/download/v2.5.2/tun2socks-windows-amd64.zip";
let ps_script = format!(
"Invoke-WebRequest -Uri '{}' -OutFile '{}' -ErrorAction Stop; \
Expand-Archive -Path '{}' -DestinationPath '{}' -Force; \
Get-ChildItem -Path '{}' -Filter '*.exe' -Recurse | Copy-Item -Destination '{}' -Force; \
Remove-Item '{}', '{}' -Recurse -Force",
url, zip_path, zip_path, temp_path, temp_path, dest_path, zip_path, temp_path
);
let output = std::process::Command::new("powershell")
.args(["-Command", &ps_script])
.current_dir(dir)
.output()?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(anyhow!("Failed to download tun2socks.exe: {stderr}"));
}
if debug {
println!("[ostp-client] tun2socks.exe downloaded and installed successfully!");
}
}
Ok(())
}
#[cfg(not(target_os = "windows"))]
pub fn download_tun2socks(_debug: bool) -> Result<()> {
Ok(())
}

View File

@ -1,91 +1,153 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
#[cfg(target_os = "windows")]
use std::sync::Arc;
use tokio::sync::watch; use tokio::sync::watch;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub async fn run_wintun_tunnel( pub async fn run_wintun_tunnel(
config: crate::config::ClientConfig,
mut shutdown: watch::Receiver<bool>, mut shutdown: watch::Receiver<bool>,
debug: bool,
) -> Result<()> { ) -> Result<()> {
use std::net::ToSocketAddrs;
use std::process::{Command, Stdio};
let debug = config.debug;
if debug { if debug {
println!("[ostp-client] Initializing Wintun adapter 'ostp_tun'..."); println!("[ostp-client] Initializing high-performance TUN tunnel via tun2socks...");
} }
// 1. Load Wintun DLL // 1. Get executable directory to locate tun2socks.exe and wintun.dll
let wintun = unsafe { wintun::load_from_path("wintun.dll") } let exe = std::env::current_exe()?;
.map_err(|e| anyhow!("Failed to load wintun.dll: {:?}", e))?; let dir = exe.parent().ok_or_else(|| anyhow!("failed to get binary directory"))?;
let tun2socks_exe = dir.join("tun2socks.exe");
// 2. Create or Open Adapter with static name "ostp_tun" if !tun2socks_exe.exists() {
let adapter = match wintun::Adapter::open(&wintun, "ostp_tun") { return Err(anyhow!("tun2socks.exe not found! Please ensure initialization downloaded it successfully."));
Ok(a) => a,
Err(_) => wintun::Adapter::create(&wintun, "ostp_tun", "OSTP TUN Adapter", None)
.map_err(|e| anyhow!("Failed to create Wintun adapter: {:?}", e))?,
};
let adapter = Arc::new(adapter);
// Set IP, Subnet and Gateway natively using netsh for bulletproof routing
if debug {
println!("[ostp-client] Configuring Wintun network settings via netsh...");
} }
let output = std::process::Command::new("netsh")
.args(["interface", "ipv4", "set", "address", "name=ostp_tun", "static", "10.1.0.2", "255.255.255.0", "10.1.0.1"]) // 2. Resolve Server IP for routing table exclusion
let server_ip = config.ostp.server_addr.to_socket_addrs()
.map_err(|e| anyhow!("Failed to resolve remote server IP: {}", e))?
.next()
.map(|addr| addr.ip())
.ok_or_else(|| anyhow!("Could not resolve host IP for routing exclusion"))?;
let server_ip_str = server_ip.to_string();
if debug {
println!("[ostp-client] Resolved remote server IP: {}", server_ip_str);
}
// 3. Run PowerShell script to configure system routes
if debug {
println!("[ostp-client] Injecting system routing tables and excluding remote proxy...");
}
let setup_script = format!(
"$remote_ip = '{}'\n\
$route = Get-NetRoute -DestinationPrefix '0.0.0.0/0' | Sort-Object RouteMetric | Select-Object -First 1\n\
$gw = $route.NextHop\n\
$ifIndex = $route.InterfaceIndex\n\
New-NetRoute -DestinationPrefix \"$remote_ip/32\" -NextHop $gw -InterfaceIndex $ifIndex -RouteMetric 1 -ErrorAction SilentlyContinue\n",
server_ip_str
);
let out = Command::new("powershell")
.args(["-Command", &setup_script])
.output()?; .output()?;
if !output.status.success() { if !out.status.success() && debug {
let stderr = String::from_utf8_lossy(&output.stderr); println!("[ostp-client] Warning: Setup routing returned: {}", String::from_utf8_lossy(&out.stderr));
println!("[ostp-client] Warning: netsh returned error: {}", stderr);
} else {
if debug {
println!("[ostp-client] Network configured. ostp_tun IP: 10.1.0.2, Gateway: 10.1.0.1");
}
} }
// Start Wintun session // 4. Prepare and launch tun2socks.exe in the background
let session = adapter.start_session(wintun::MAX_RING_CAPACITY) let proxy_url = format!("socks5://{}", config.local_proxy.bind_addr);
.map_err(|e| anyhow!("Failed to start Wintun session: {:?}", e))?;
let session = Arc::new(session);
if debug { if debug {
println!("[ostp-client] TUN tunnel 'ostp_tun' is active and intercepting packets!"); println!("[ostp-client] Spawning tun2socks daemon pointing to {}", proxy_url);
} }
// Spawn Packet Receiver Loop to read packets from Windows stack let mut child = Command::new(&tun2socks_exe)
let rx_session = session.clone(); .args([
tokio::task::spawn_blocking(move || { "-device", "ostp_tun",
loop { "-proxy", &proxy_url,
match rx_session.receive_blocking() { "-loglevel", if debug { "debug" } else { "error" }
Ok(packet) => { ])
let bytes = packet.bytes(); .current_dir(dir)
if bytes.len() >= 20 { .stdout(Stdio::piped())
let proto = bytes[9]; .stderr(Stdio::piped())
let src_ip = format!("{}.{}.{}.{}", bytes[12], bytes[13], bytes[14], bytes[15]); .spawn()
let dest_ip = format!("{}.{}.{}.{}", bytes[16], bytes[17], bytes[18], bytes[19]); .map_err(|e| anyhow!("Failed to launch tun2socks.exe background process: {}", e))?;
if debug {
println!("[TUN Packet] Proto={}, Src={}, Dest={}, Len={}", proto, src_ip, dest_ip, bytes.len());
}
}
}
Err(_) => break,
}
}
});
// Wait for shutdown signal // 5. Once tun2socks creates the interface, apply network settings (IP, metric, DNS)
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
if debug {
println!("[ostp-client] Applying network configurations onto 'ostp_tun' interface...");
}
let net_setup = "\
netsh interface ipv4 set address name=\"ostp_tun\" static 10.1.0.2 255.255.255.0 10.1.0.1\n\
netsh interface ipv4 set interface name=\"ostp_tun\" metric=5\n\
netsh interface ipv4 set dnsservers name=\"ostp_tun\" static 1.1.1.1 primary\n";
let _ = Command::new("powershell")
.args(["-Command", net_setup])
.output()?;
println!("[client] TUN Tunnel established, internet traffic is now routing through OSTP.");
// 6. Spawn thread to keep logging tun2socks output if in debug mode
let mut stdout = child.stdout.take();
let mut stderr = child.stderr.take();
if debug {
std::thread::spawn(move || {
use std::io::{BufRead, BufReader};
if let Some(out) = stdout.take() {
let reader = BufReader::new(out);
for line in reader.lines().map_while(Result::ok) {
println!("[tun2socks] {}", line);
}
}
});
std::thread::spawn(move || {
use std::io::{BufRead, BufReader};
if let Some(err) = stderr.take() {
let reader = BufReader::new(err);
for line in reader.lines().map_while(Result::ok) {
println!("[tun2socks err] {}", line);
}
}
});
}
// 7. Wait for shutdown signal
let _ = shutdown.changed().await; let _ = shutdown.changed().await;
if debug { println!("[client] Deactivating TUN tunnel and restoring system network topology...");
println!("[ostp-client] Shutting down Wintun adapter...");
} // 8. Terminate tun2socks
let _ = child.kill();
// 9. Run cleanup routing script
let cleanup_script = format!(
"$remote_ip = '{}'\n\
Remove-NetRoute -DestinationPrefix \"$remote_ip/32\" -Confirm:$false -ErrorAction SilentlyContinue\n",
server_ip_str
);
let _ = Command::new("powershell")
.args(["-Command", &cleanup_script])
.output()?;
println!("[client] TUN Tunnel stopped.");
Ok(()) Ok(())
} }
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
pub async fn run_wintun_tunnel( pub async fn run_wintun_tunnel(
_config: crate::config::ClientConfig,
_shutdown: watch::Receiver<bool>, _shutdown: watch::Receiver<bool>,
_debug: bool,
) -> Result<()> { ) -> Result<()> {
Err(anyhow!("Wintun is only supported on Windows!")) Err(anyhow!("Wintun is only supported on Windows!"))
} }