mirror of
https://github.com/therealaleph/MasterHttpRelayVPN-RUST.git
synced 2026-05-18 08:34:35 +03:00
fb552c227d
Ships PR #173 (event-driven drain) plus three operational improvements: PR #173 — long-poll tunnel mode. The tunnel-node's batch drain switched from a fixed 150 ms sleep to an event-driven Notify wait; idle sessions long-poll up to 5 s and wake on the first byte from upstream. Push notifications and chat messages now arrive in roughly RTT instead of waiting for the next client poll tick. Backward compat with pre-#173 tunnel-nodes is automatic via a sticky AtomicBool that detects fast empty replies and reverts to the legacy cadence. 92 client tests + 17 tunnel-node tests pass, including end-to-end TCP-pair verification of the notify wiring. Docker image for tunnel-node. Adds a hardened Dockerfile (BuildKit cache mounts, non-root runtime user, ca-certificates for HTTPS upstreams) and a .dockerignore to keep build context small. New `tunnel-docker` job in the release workflow builds + pushes multi-arch (linux/amd64 + linux/arm64) to ghcr.io/therealaleph/mhrv-tunnel-node with `:latest`, `:1.5`, and `:1.5.0` tags on every release. Setting up Full Tunnel mode goes from "rustup + cargo build on a 1 GB VPS" (which fails on memory half the time) to a one-liner. tunnel-node/README.md updated with prebuilt-image + docker-compose recipes. Brief Persian release note in Telegram caption. The release-post caption now leads with a `<blockquote>`-wrapped FA bullet headlines extracted from `docs/changelog/v<ver>.md`, above the existing two links (repo + release). Markdown links → Telegram HTML <a> for clickability. Cap-budget-aware truncation at bullet boundaries keeps total caption under Telegram's 1024-char limit. Headlines-only rather than full bullets so multiple "what's new" items fit comfortably (the full bullets remain on the GH release page and as the optional --with-changelog reply-threaded message). GitHub Releases page bodies now lead with the changelog content (Persian section + `---` + English) instead of just a Full Changelog comparison link. The auto comparison link is appended at the bottom via `append_body: true` rather than removed. Workflow changes: - New `permissions: packages: write` at the workflow level (required for ghcr push via docker/login-action). - New `tunnel-docker` job needs `build` (not the full matrix) to serialize the QEMU buildx layer with the matrix cache. - Release job composes the body from `docs/changelog/v${VER}.md` in a pre-step that handles both tag-push and workflow_dispatch paths (uses inputs.version || github.ref_name like the rest of the workflow). Tested locally: - `cargo test` — 92 lib tests pass - `cargo test -p mhrv-tunnel-node` — 17 tests pass - `docker build` of tunnel-node Dockerfile — 32 MB image, runs as non-root, /health returns "ok", auth rejection works correctly, legitimate requests open sessions to remote hosts - Telegram script `--dry-run` mode added; rendered captions for v1.4.0, v1.4.1, v1.5.0 all fit under 900 chars Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
109 lines
4.0 KiB
TOML
109 lines
4.0 KiB
TOML
[package]
|
|
name = "mhrv-rs"
|
|
version = "1.5.0"
|
|
edition = "2021"
|
|
description = "Rust port of MasterHttpRelayVPN -- DPI bypass via Google Apps Script relay with domain fronting"
|
|
license = "MIT"
|
|
|
|
[lib]
|
|
name = "mhrv_rs"
|
|
path = "src/lib.rs"
|
|
# `cdylib` lets the Android app dlopen libmhrv_rs.so via System.loadLibrary.
|
|
# `rlib` keeps the desktop binaries linking normally — same .rlib is used
|
|
# for `mhrv-rs` and `mhrv-rs-ui` builds on macOS/Linux/Windows.
|
|
crate-type = ["rlib", "cdylib"]
|
|
|
|
[[bin]]
|
|
name = "mhrv-rs"
|
|
path = "src/main.rs"
|
|
|
|
[[bin]]
|
|
name = "mhrv-rs-ui"
|
|
path = "src/bin/ui.rs"
|
|
required-features = ["ui"]
|
|
|
|
[features]
|
|
default = []
|
|
ui = ["dep:eframe"]
|
|
|
|
[dependencies]
|
|
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "time", "io-util", "signal", "sync"] }
|
|
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"] }
|
|
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] }
|
|
rustls-pemfile = "2"
|
|
webpki-roots = "0.26"
|
|
rcgen = { version = "0.13", features = ["x509-parser"] }
|
|
rustls-pki-types = "1"
|
|
time = "0.3"
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|
thiserror = "2"
|
|
base64 = "0.22"
|
|
bytes = "1"
|
|
httparse = "1"
|
|
rand = "0.8"
|
|
h2 = "0.4"
|
|
http = "1"
|
|
flate2 = "1"
|
|
directories = "5"
|
|
futures-util = { version = "0.3", default-features = false, features = ["std"] }
|
|
# 64-bit atomics on 32-bit MIPS/ARMv5 targets. Rust's std AtomicU64 is
|
|
# only available on targets that expose native 64-bit atomics, which
|
|
# mipsel-unknown-linux-musl does not — `AtomicU64` resolves to "no
|
|
# such name in sync::atomic" and the whole crate fails to build. The
|
|
# `fallback` feature uses a global spinlock when the target can't do
|
|
# 64-bit atomically; on x86_64 / aarch64 / armv7 / etc. it compiles
|
|
# down to the native instructions with no overhead.
|
|
portable-atomic = { version = "1", features = ["fallback"] }
|
|
|
|
# Optional UI dep: only pulled in when --features ui is set.
|
|
# Both `glow` (OpenGL 2+) and `wgpu` (DX12/Vulkan/Metal) are compiled in;
|
|
# the binary picks one at startup — glow by default for compat with the
|
|
# egui look-and-feel we've been shipping, but falls back to wgpu when
|
|
# `MHRV_RENDERER=wgpu` is set. Issue #28: users on older Windows
|
|
# hardware / RDP / VMs without OpenGL 2.0 crash with
|
|
# `egui_glow requires opengl 2.0+` — the wgpu backend uses DX12/Vulkan
|
|
# instead and covers those boxes.
|
|
eframe = { version = "0.28", default-features = false, features = [
|
|
"default_fonts",
|
|
"glow",
|
|
"wgpu",
|
|
"persistence",
|
|
], optional = true }
|
|
url = "2.5.8"
|
|
|
|
# Unix-only deps. Must come after `[dependencies]` because starting a new
|
|
# table here otherwise ends the main one — anything below it (incl. eframe)
|
|
# would end up scoped to cfg(unix) and disappear on Windows builds.
|
|
# libc is referenced for the RLIMIT_NOFILE bump (issue #8 — OpenWRT routers
|
|
# ship a very low fd limit that fills up fast under browser load). Already
|
|
# pulled in transitively via tokio, so zero new weight.
|
|
[target.'cfg(unix)'.dependencies]
|
|
libc = "0.2"
|
|
|
|
# Android-only deps: jni gives us the extern "system" wrappers used in
|
|
# src/android_jni.rs; zero cost on any other platform because the whole
|
|
# module is `#[cfg(target_os = "android")]`.
|
|
#
|
|
# tun2proxy is the TUN <-> SOCKS5 bridge — it reads raw IP packets from the
|
|
# fd VpnService hands us, runs a userspace TCP/IP stack (smoltcp under the
|
|
# hood), and funnels every TCP/UDP flow through our local SOCKS5. Without
|
|
# this, VpnService establishes a TUN device nothing reads from and all
|
|
# traffic black-holes (symptom: Chrome shows DNS_PROBE_STARTED).
|
|
[target.'cfg(target_os = "android")'.dependencies]
|
|
jni = { version = "0.21", default-features = false }
|
|
tun2proxy = { version = "0.7", default-features = false }
|
|
|
|
[dev-dependencies]
|
|
# Used in mitm tests to sanity-check the cert extensions we emit.
|
|
x509-parser = "0.16"
|
|
|
|
[profile.release]
|
|
panic = "abort"
|
|
codegen-units = 1
|
|
lto = true
|
|
opt-level = 3
|
|
strip = true
|