mirror of
https://github.com/therealaleph/MasterHttpRelayVPN-RUST.git
synced 2026-05-17 21:24:48 +03:00
feat: enable udpgw via tun2proxy CLI API — no fork needed (#271)
Uses tun2proxy_run_with_cli_args (the C API) via dlsym instead of modifying the JNI run() signature. The upstream tun2proxy maintainer recommended this path — the CLI API accepts --udpgw-server natively. - Cargo.toml: enable udpgw feature, remove [patch.crates-io] - MhrvVpnService.kt: build CLI args with --udpgw-server in full mode - Native.kt + android_jni.rs: dlsym wrapper for the C API - Tun2proxy.kt: reverted to upstream signature No fork, no patch, no submodule. Co-authored-by: yyoyoian-pixel <279225925+yyoyoian-pixel@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Generated
+2
-1
@@ -3961,7 +3961,8 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tun2proxy"
|
||||
version = "0.7.21"
|
||||
source = "git+https://github.com/yyoyoian-pixel/tun2proxy?branch=feat%2Fudpgw-jni-param#dfc24ed12cdee69987bdd321ea55c6b940f2d0f0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336ad07beb04a9e219972fcdc54a71d2586cdfd35ac03551a629e4ca328db3c"
|
||||
dependencies = [
|
||||
"android_logger",
|
||||
"async-trait",
|
||||
|
||||
@@ -100,12 +100,6 @@ tun2proxy = { version = "0.7", default-features = false, features = ["udpgw"] }
|
||||
# Used in mitm tests to sanity-check the cert extensions we emit.
|
||||
x509-parser = "0.16"
|
||||
|
||||
# Temporary patch: adds udpgw_server parameter to the Android JNI run()
|
||||
# function. Upstream PR: https://github.com/tun2proxy/tun2proxy/pull/247
|
||||
# Remove this section once tun2proxy >= 0.8 ships with the change.
|
||||
[patch.crates-io]
|
||||
tun2proxy = { git = "https://github.com/yyoyoian-pixel/tun2proxy", branch = "feat/udpgw-jni-param" }
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
codegen-units = 1
|
||||
|
||||
@@ -59,7 +59,6 @@ object Tun2proxy {
|
||||
tunMtu: Char,
|
||||
verbosity: Int,
|
||||
dnsStrategy: Int,
|
||||
udpgwServer: String,
|
||||
): Int
|
||||
|
||||
/** Signals the running `run()` to shut down. Idempotent. */
|
||||
|
||||
@@ -259,21 +259,20 @@ class MhrvVpnService : VpnService() {
|
||||
// the sole owner once it's running.
|
||||
val detachedFd = parcelFd.detachFd()
|
||||
tun2proxyRunning.set(true)
|
||||
// In full mode, enable udpgw so UDP traffic (DNS, QUIC, …) is
|
||||
// forwarded through the tunnel-node's native udpgw handler.
|
||||
// 198.18.0.1:7300 is a magic address the tunnel-node intercepts.
|
||||
val udpgwAddr = if (cfg.mode == Mode.FULL) "198.18.0.1:7300" else ""
|
||||
// Use tun2proxy_run_with_cli_args C API via dlsym — gives full
|
||||
// CLI flexibility including --udpgw-server, no fork needed.
|
||||
val cliArgs = buildString {
|
||||
append("tun2proxy")
|
||||
append(" --proxy socks5://127.0.0.1:$socks5Port")
|
||||
append(" --tun-fd $detachedFd")
|
||||
append(" --dns virtual")
|
||||
append(" --verbosity info")
|
||||
append(" --close-fd-on-drop true")
|
||||
if (cfg.mode == Mode.FULL) append(" --udpgw-server 198.18.0.1:7300")
|
||||
}
|
||||
val worker = Thread({
|
||||
try {
|
||||
val rc = Tun2proxy.run(
|
||||
"socks5://127.0.0.1:$socks5Port",
|
||||
detachedFd,
|
||||
/* closeFdOnDrop = */ true,
|
||||
MTU.toChar(),
|
||||
/* verbosity = info */ 3,
|
||||
/* dnsStrategy = virtual */ 0,
|
||||
udpgwAddr,
|
||||
)
|
||||
val rc = Native.runTun2proxy(cliArgs, MTU)
|
||||
Log.i(TAG, "tun2proxy exited rc=$rc")
|
||||
} catch (t: Throwable) {
|
||||
Log.e(TAG, "tun2proxy crashed: ${t.message}", t)
|
||||
|
||||
@@ -95,4 +95,14 @@ object Native {
|
||||
* Cheap — just reads atomics. Safe to poll on a second-scale timer.
|
||||
*/
|
||||
external fun statsJson(handle: Long): String
|
||||
|
||||
/**
|
||||
* Start tun2proxy via its CLI args C API (`tun2proxy_run_with_cli_args`).
|
||||
* Resolved at runtime via dlsym from libtun2proxy.so — no fork needed.
|
||||
*
|
||||
* @param cliArgs full CLI string, e.g. "tun2proxy --proxy socks5://... --tun-fd 42 --udpgw-server 198.18.0.1:7300"
|
||||
* @param tunMtu TUN MTU (typically 1500)
|
||||
* @return 0 on normal shutdown, negative on error. BLOCKS.
|
||||
*/
|
||||
external fun runTun2proxy(cliArgs: String, tunMtu: Int): Int
|
||||
}
|
||||
|
||||
@@ -482,3 +482,53 @@ pub extern "system" fn Java_com_therealaleph_mhrv_Native_statsJson<'a>(
|
||||
}));
|
||||
env.new_string(out).map(|s| s.into_raw()).unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// tun2proxy CLI API wrapper (dlsym — no fork or patch needed)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// `Native.runTun2proxy(cliArgs, tunMtu)` -> int
|
||||
///
|
||||
/// Calls `tun2proxy_run_with_cli_args` from libtun2proxy.so via dlsym.
|
||||
/// This is the C API the tun2proxy maintainer recommends for callers that
|
||||
/// need full CLI flexibility (e.g. --udpgw-server). BLOCKS until shutdown.
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_therealaleph_mhrv_Native_runTun2proxy<'a>(
|
||||
mut env: JNIEnv<'a>,
|
||||
_class: JClass,
|
||||
cli_args: JString,
|
||||
tun_mtu: jni::sys::jint,
|
||||
) -> jni::sys::jint {
|
||||
safe(-1, AssertUnwindSafe(|| {
|
||||
let args_str = jstring_to_string(&mut env, &cli_args);
|
||||
tracing::info!("runTun2proxy: cli={}", args_str);
|
||||
|
||||
unsafe {
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
let lib = CString::new("libtun2proxy.so").unwrap();
|
||||
let handle = libc::dlopen(lib.as_ptr(), libc::RTLD_NOW);
|
||||
if handle.is_null() {
|
||||
let err = CStr::from_ptr(libc::dlerror());
|
||||
tracing::error!("dlopen libtun2proxy.so failed: {:?}", err);
|
||||
return -10;
|
||||
}
|
||||
|
||||
let sym = CString::new("tun2proxy_run_with_cli_args").unwrap();
|
||||
let func = libc::dlsym(handle, sym.as_ptr());
|
||||
if func.is_null() {
|
||||
let err = CStr::from_ptr(libc::dlerror());
|
||||
tracing::error!("dlsym tun2proxy_run_with_cli_args: {:?}", err);
|
||||
libc::dlclose(handle);
|
||||
return -11;
|
||||
}
|
||||
|
||||
type RunFn = unsafe extern "C" fn(*const std::ffi::c_char, u16, bool) -> i32;
|
||||
let run: RunFn = std::mem::transmute(func);
|
||||
let c_args = CString::new(args_str).unwrap();
|
||||
let rc = run(c_args.as_ptr(), tun_mtu as u16, false);
|
||||
libc::dlclose(handle);
|
||||
rc
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user