refactor: pre-package Wintun and tun2socks into archives via CI/CD and purge runtime downloader

This commit is contained in:
ospab 2026-05-15 17:07:18 +03:00
parent 9fa93ebce5
commit 6ae43a8f41
7 changed files with 68 additions and 190 deletions

View File

@ -24,14 +24,20 @@ jobs:
target: x86_64-pc-windows-msvc
artifact_name: ostp.exe
release_name: ostp-windows-amd64.zip
tun2socks_arch: windows-amd64
wintun_arch: amd64
- os: windows-latest
target: i686-pc-windows-msvc
artifact_name: ostp.exe
release_name: ostp-windows-386.zip
tun2socks_arch: windows-386
wintun_arch: x86
- os: windows-latest
target: aarch64-pc-windows-msvc
artifact_name: ostp.exe
release_name: ostp-windows-arm64.zip
tun2socks_arch: windows-arm64
wintun_arch: arm64
# ==========================================
# 🍏 APPLE DARWIN (macOS)
@ -40,10 +46,12 @@ jobs:
target: x86_64-apple-darwin
artifact_name: ostp
release_name: ostp-darwin-amd64.tar.gz
tun2socks_arch: darwin-amd64
- os: macos-latest
target: aarch64-apple-darwin
artifact_name: ostp
release_name: ostp-darwin-arm64.tar.gz
tun2socks_arch: darwin-arm64
# ==========================================
# 🐧 LINUX & FreeBSD STANDARD
@ -52,24 +60,29 @@ jobs:
target: x86_64-unknown-linux-musl
artifact_name: ostp
release_name: ostp-linux-amd64.tar.gz
tun2socks_arch: linux-amd64
- os: ubuntu-latest
target: i686-unknown-linux-musl
artifact_name: ostp
release_name: ostp-linux-386.tar.gz
tun2socks_arch: linux-386
- os: ubuntu-latest
target: aarch64-unknown-linux-musl
artifact_name: ostp
release_name: ostp-linux-arm64.tar.gz
tun2socks_arch: linux-arm64
use_cross: true
- os: ubuntu-latest
target: armv7-unknown-linux-musleabihf
artifact_name: ostp
release_name: ostp-linux-armv7.tar.gz
tun2socks_arch: linux-armv7
use_cross: true
- os: ubuntu-latest
target: x86_64-unknown-freebsd
artifact_name: ostp
release_name: ostp-freebsd-amd64.tar.gz
tun2socks_arch: freebsd-amd64
use_cross: true
# ==========================================
@ -79,12 +92,14 @@ jobs:
target: mipsel-unknown-linux-musl
artifact_name: ostp
release_name: ostp-linux-mipsle.tar.gz
tun2socks_arch: linux-mipsle
use_cross: true
toolchain: nightly
- os: ubuntu-latest
target: riscv64gc-unknown-linux-gnu
artifact_name: ostp
release_name: ostp-linux-riscv64.tar.gz
tun2socks_arch: linux-riscv64
use_cross: true
# ==========================================
@ -94,6 +109,7 @@ jobs:
target: aarch64-linux-android
artifact_name: ostp
release_name: ostp-android-arm64.tar.gz
tun2socks_arch: android-arm64
use_cross: true
steps:
@ -137,18 +153,63 @@ jobs:
cargo install cross --git https://github.com/cross-rs/cross.git
cross build --release --target ${{ matrix.target }} --bin ostp
- name: Inject Win32 Driver Dependencies (Windows)
if: ${{ matrix.os == 'windows-latest' && matrix.tun2socks_arch }}
shell: pwsh
run: |
cd target/${{ matrix.target }}/release
$ProgressPreference = 'SilentlyContinue'
# 1. Acquire tun2socks
Invoke-WebRequest -Uri "https://github.com/xjasonlyu/tun2socks/releases/download/v2.6.0/tun2socks-${{ matrix.tun2socks_arch }}.zip" -OutFile "tun2socks.zip"
Expand-Archive -Path "tun2socks.zip" -DestinationPath "tun_temp" -Force
Get-ChildItem -Path "tun_temp" -Filter "*.exe" -Recurse | Copy-Item -Destination "." -Force
# 2. Acquire wintun
Invoke-WebRequest -Uri "https://www.wintun.net/builds/wintun-0.14.1.zip" -OutFile "wintun.zip"
Expand-Archive -Path "wintun.zip" -DestinationPath "wintun_temp" -Force
Get-ChildItem -Path "wintun_temp" -Filter "wintun.dll" -Recurse | Where-Object { $_.FullName -match 'bin[\\/]${{ matrix.wintun_arch }}[\\/]' } | Copy-Item -Destination "." -Force
# Cleanup
Remove-Item "tun2socks.zip", "tun_temp", "wintun.zip", "wintun_temp" -Recurse -Force
- name: Inject Unix Driver Dependencies (Unix)
if: ${{ matrix.os != 'windows-latest' && matrix.tun2socks_arch }}
shell: bash
run: |
cd target/${{ matrix.target }}/release
# Fetch using correct extension (Linux = .tar.gz, Darwin/FreeBSD = .zip)
if [[ "${{ matrix.tun2socks_arch }}" == *"linux"* ]]; then
URL="https://github.com/xjasonlyu/tun2socks/releases/download/v2.6.0/tun2socks-${{ matrix.tun2socks_arch }}.tar.gz"
curl -L "$URL" -o "tun2socks.tar.gz"
tar -xzf "tun2socks.tar.gz"
find . -maxdepth 2 -name "tun2socks*" ! -name "*.tar.gz" -type f -exec mv {} ./tun2socks \;
rm -f "tun2socks.tar.gz"
else
URL="https://github.com/xjasonlyu/tun2socks/releases/download/v2.6.0/tun2socks-${{ matrix.tun2socks_arch }}.zip"
curl -L "$URL" -o "tun2socks.zip"
unzip -o "tun2socks.zip"
find . -maxdepth 2 -name "tun2socks*" ! -name "*.zip" -type f -exec mv {} ./tun2socks \;
rm -f "tun2socks.zip"
fi
chmod +x tun2socks || true
- name: Package release artifact (Windows)
if: ${{ matrix.os == 'windows-latest' }}
shell: pwsh
run: |
cd target/${{ matrix.target }}/release
Compress-Archive -Path ${{ matrix.artifact_name }} -DestinationPath ../../../${{ matrix.release_name }}
$files = @("${{ matrix.artifact_name }}")
if (Test-Path "tun2socks.exe") { $files += "tun2socks.exe" }
if (Test-Path "wintun.dll") { $files += "wintun.dll" }
Compress-Archive -Path $files -DestinationPath ../../../${{ matrix.release_name }}
- name: Package release artifact (Unix Systems)
if: ${{ matrix.os != 'windows-latest' }}
run: |
cd target/${{ matrix.target }}/release
tar -czf ../../../${{ matrix.release_name }} ${{ matrix.artifact_name }}
FILES="${{ matrix.artifact_name }}"
if [ -f "tun2socks" ]; then
FILES="$FILES tun2socks"
fi
tar -czf ../../../${{ matrix.release_name }} $FILES
- name: Inject artifact to Global GitHub Release Assets
if: ${{ startsWith(github.ref, 'refs/tags/') }}

8
Cargo.lock generated
View File

@ -476,7 +476,7 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "ostp"
version = "0.1.26"
version = "0.1.31"
dependencies = [
"anyhow",
"base64",
@ -491,7 +491,7 @@ dependencies = [
[[package]]
name = "ostp-client"
version = "0.1.26"
version = "0.1.31"
dependencies = [
"anyhow",
"bytes",
@ -506,7 +506,7 @@ dependencies = [
[[package]]
name = "ostp-core"
version = "0.1.26"
version = "0.1.31"
dependencies = [
"anyhow",
"async-trait",
@ -538,7 +538,7 @@ dependencies = [
[[package]]
name = "ostp-server"
version = "0.1.26"
version = "0.1.31"
dependencies = [
"anyhow",
"bytes",

View File

@ -116,10 +116,6 @@ pub async fn run_client(config: crate::config::ClientConfig) -> Result<()> {
println!("[ostp-client] WARNING: process exclusions are not supported in the current TUN implementation");
}
if config.mode == "tun" {
tunnel::download_wintun_dll(config.debug)?;
tunnel::download_tun2socks(config.debug)?;
}
let (proxy_events_tx, proxy_events_rx) = mpsc::channel(10000);
let (client_msgs_tx, client_msgs_rx) = mpsc::channel(10000);

View File

@ -18,9 +18,6 @@ pub async fn run_linux_tunnel(
println!("[ostp-client] Starting Linux TUN handler initialization...");
}
// 1. Automatically ensure tun2socks binary is downloaded and present
super::download_tun2socks(debug)?;
let exe = std::env::current_exe()?;
let dir = exe.parent().ok_or_else(|| anyhow!("failed to get binary directory"))?;

View File

@ -1,11 +1,7 @@
mod proxy;
mod wintun_downloader;
mod wintun_handler;
mod linux_handler;
pub use wintun_downloader::download_wintun_dll;
pub use wintun_downloader::download_tun2socks;
pub async fn run_tun_tunnel(
config: crate::config::ClientConfig,
shutdown: watch::Receiver<bool>,

View File

@ -1,168 +0,0 @@
#![allow(unused_imports)]
use anyhow::Result;
#[cfg(target_os = "windows")]
use anyhow::anyhow;
use std::path::PathBuf;
#[cfg(target_os = "windows")]
pub fn download_wintun_dll(debug: bool) -> Result<()> {
let exe = std::env::current_exe()?;
let dir = exe.parent().ok_or_else(|| anyhow!("failed to get binary directory"))?;
let dll_path = dir.join("wintun.dll");
if !dll_path.exists() {
if debug {
println!("[ostp-client] wintun.dll not found. Downloading automatically...");
}
// Correctly map compilation target architecture to Wintun zip layout folder structure
let arch = if cfg!(target_arch = "x86_64") {
"amd64"
} else if cfg!(target_arch = "aarch64") {
"arm64"
} else if cfg!(target_arch = "arm") {
"arm"
} else {
"x86"
};
let zip_path = dir.join("wintun.zip").to_string_lossy().replace('\\', "/");
let temp_path = dir.join("wintun_temp").to_string_lossy().replace('\\', "/");
let dll_dest = dll_path.to_string_lossy().replace('\\', "/");
// Explicitly filter via Where-Object to select ONLY the single architecture matching dll.
// This guarantees we never overwrite the correct x64 dll with x86/ARM formats during Expand-Archive recursions.
let ps_script = format!(
"$ProgressPreference = 'SilentlyContinue'; \
Invoke-WebRequest -Uri 'https://www.wintun.net/builds/wintun-0.14.1.zip' -OutFile '{}' -UseBasicParsing -ErrorAction Stop; \
Expand-Archive -Path '{}' -DestinationPath '{}' -Force; \
Get-ChildItem -Path '{}' -Filter 'wintun.dll' -Recurse | Where-Object {{ $_.FullName -match 'bin[\\\\/]{}[\\\\/]' }} | Copy-Item -Destination '{}' -Force; \
Remove-Item '{}', '{}' -Recurse -Force",
zip_path, zip_path, temp_path, temp_path, arch, dll_dest, 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 and extract wintun.dll for architecture {}: {}", arch, stderr));
}
if debug {
println!("[ostp-client] wintun.dll ({}) successfully downloaded and registered!", arch);
}
}
Ok(())
}
#[cfg(not(target_os = "windows"))]
pub fn download_wintun_dll(_debug: bool) -> Result<()> {
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 arch = if cfg!(target_arch = "x86_64") {
"amd64"
} else if cfg!(target_arch = "aarch64") {
"arm64"
} else if cfg!(target_arch = "arm") {
"arm"
} else {
"386"
};
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 = format!("https://github.com/xjasonlyu/tun2socks/releases/download/v2.6.0/tun2socks-windows-{}.zip", arch);
let ps_script = format!(
"$ProgressPreference = 'SilentlyContinue'; \
Invoke-WebRequest -Uri '{}' -OutFile '{}' -UseBasicParsing -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!", arch);
}
}
Ok(())
}
#[cfg(target_os = "linux")]
pub fn download_tun2socks(debug: bool) -> Result<()> {
let exe = std::env::current_exe()?;
let dir = exe.parent().ok_or_else(|| anyhow::anyhow!("failed to get binary directory"))?;
let tun2socks_path = dir.join("tun2socks");
if !tun2socks_path.exists() {
if debug {
println!("[ostp-client] tun2socks not found. Downloading automatically for Linux...");
}
let arch = if cfg!(target_arch = "x86_64") {
"amd64"
} else if cfg!(target_arch = "aarch64") {
"arm64"
} else if cfg!(target_arch = "arm") {
"arm"
} else {
"386"
};
let tar_path = dir.join("tun2socks.tar.gz").to_string_lossy().into_owned();
let dest_path = tun2socks_path.to_string_lossy().into_owned();
let url = format!("https://github.com/xjasonlyu/tun2socks/releases/download/v2.6.0/tun2socks-linux-{}.tar.gz", arch);
let sh_script = format!(
"curl -L -o '{}' '{}' && tar -xzf '{}' -C '{}' --wildcards '*/tun2socks' --strip-components=1 || tar -xzf '{}' -C '{}' tun2socks; \
chmod +x '{}'; \
rm -f '{}'",
tar_path, url, tar_path, dir.to_string_lossy(), tar_path, dir.to_string_lossy(), dest_path, tar_path
);
let output = std::process::Command::new("sh")
.args(["-c", &sh_script])
.current_dir(dir)
.output()?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(anyhow::anyhow!("Failed to download tun2socks for Linux: {}", stderr));
}
if debug {
println!("[ostp-client] tun2socks ({}) downloaded and installed successfully!", arch);
}
}
Ok(())
}
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
pub fn download_tun2socks(_debug: bool) -> Result<()> {
Err(anyhow::anyhow!("Operating system unsupported, text an issue at github."))
}

View File

@ -15,16 +15,12 @@ pub async fn run_wintun_tunnel(
println!("[ostp-client] Initializing high-performance TUN tunnel via tun2socks...");
}
// 1. Automatically ensure Wintun and tun2socks dependencies are downloaded and present
super::download_wintun_dll(debug)?;
super::download_tun2socks(debug)?;
let exe = std::env::current_exe()?;
let dir = exe.parent().ok_or_else(|| anyhow!("failed to get binary directory"))?;
let tun2socks_exe = dir.join("tun2socks.exe");
if !tun2socks_exe.exists() {
return Err(anyhow!("tun2socks.exe not found! Even after download attempt, binary remains missing."));
return Err(anyhow!("tun2socks.exe not found in current directory! Please make sure the pre-packaged dependency is present near the executable."));
}
// 2. Resolve Server IP for routing table exclusion