MEHS - Multiplexed Encrypted Hybrid Stack
MEHS is a proxy/tunnel core for MehtorVPN. It carries TCP, UDP, and DNS traffic over an authenticated,
encrypted TLS 1.3 session on TLS/TCP or QUIC, using the mehs-data/1 profile.
- Local proxy mode: SOCKS5 (TCP and optional UDP ASSOCIATE) and HTTP CONNECT listeners on loopback.
- TUN mode: a system-wide virtual interface with a client-side userspace TCP/IP stack. No special server gateway is needed.
The protocol is evolving, and no independent security audit has been completed. Matching protocol numbers do not certify mixed-release compatibility. Use matching client and server packages. See the security policy before handling real user traffic.
Downloads and runtime requirements
Obtain prebuilt packages and SHA256SUMS.txt from Releases &
downloads.
| Package | Contents |
|---|---|
mehs-server-VERSION-linux-x86_64.tar.gz |
Server for Debian 13 Linux x86_64. |
mehs-client-VERSION-linux-x86_64.tar.gz |
mehs, libmehs_client_ffi.so, C API header. |
mehs-client-VERSION-windows-{x64,x86,arm64}.zip |
mehs.exe, mehs_client_ffi.dll, matching
wintun.dll, C API header.
|
mehs-client-VERSION-android.zip |
jniLibs/{arm64-v8a,armeabi-v7a,x86_64}/{libmehs_client_ffi.so,libc++_shared.so},
C API header, NDK notices. |
mehs-client-VERSION-ios.zip |
Device and universal simulator MEHS.xcframework, C API header. |
Linux release binaries need the system C++ runtime (libstdc++6 on Debian).
Compatibility with distributions older than Debian 13 is not certified.
Windows requires the Microsoft Visual C++
v14 Redistributable
matching the package architecture. Wintun must match the executable architecture.
Quick start
Prepare certificates, credentials, listener addresses, and policy using the server guide. Replace all sample credentials. On Debian/Linux:
sudo MEHS_SERVER_CONFIG=/etc/mehs/server.json ./mehs-server
Start the client in local proxy mode:
export MEHS_CLIENT_SECRET='your-client-secret'
./mehs --control vpn.example.com:8443 --client-id laptop --ca-file ca.pem \
--socks-bind 127.0.0.1:1080 --http-bind 127.0.0.1:8080 --remote-dns
Start a system-wide TUN (root/administrator required; Windows needs wintun.dll beside
mehs.exe):
sudo -E ./mehs --control vpn.example.com:8443 --client-id laptop --ca-file ca.pem \
--mode tun --tun-exclude 192.168.0.0/16 --tun-exclude 10.0.0.0/8 \
--tun-exclude 172.16.0.0/12
Adjust LAN exclusions for your network. Add --udp-associate in proxy mode for SOCKS5 calls
or games.
Remote DNS and SOCKS5 UDP are opt-in. TUN handles UDP and DNS transparently.
For QUIC, use --transport quic --data vpn.example.com:8444.
TUN routes are removed on exit. See all CLI options and recovery rules.
Operating principles and design targets
The host supplies configuration; MEHS owns upstream connections, transport selection, reconnect/recovery, session lifecycle, and local proxy listeners. Platform adapters integrate with the operating system. The following are design targets, not a claim that every target is verified on every platform.
- One shared protocol/session/selection/recovery policy, with platform-specific host adapters.
- Authenticated MEHS frames over TCP/TLS and QUIC, optionally carried in HTTP/2 or HTTP/3 streams.
- Per-application routing with
apps.bypass,apps.only,--app-bypass, and--app-onlyon Linux and Windows. - Selection based on measured RTT, jitter, throughput, packet loss, and stability, not the newest transport.
- Make-before-break switching: authenticate the candidate, move traffic, drain the previous path, then close it.
- A logical session with ordering, acknowledgements, duplicate suppression, bounded buffers, and explicit failure.
- One server and one main configuration for the initial deployment model.
- Honest readiness, establishment, selected-transport, metric, warning, and terminal-error status reporting.
An underlying TCP connection cannot become QUIC. Continuity means preserving logical-session traffic semantics over separate connections. No system can guarantee zero delay or loss through permanent server failure, process termination, device suspension, exhausted buffers, or indefinite network loss.
Transport modes
The default path is TLS 1.3 with ALPN mehs-data/1. QUIC uses its TLS 1.3 handshake.
Older TLS versions must not be used as downgrade fallbacks.
| Profile | Carrier shape |
|---|---|
mehs-data/1 |
Raw MEHS frames over TLS/TCP or QUIC. |
trusttunnel |
HTTP CONNECT tunnel. |
xhttp |
Streaming POST on http_path. |
notmehs |
POST with x-padding; CONNECT tolerated; decoy page on other requests. |
HTTP profiles use HTTP/2 over TCP or HTTP/3 over QUIC. A server may enable several profiles in
transport_profiles and dispatch by ALPN. These are MEHS-native carriers, not compatible
with third-party TrustTunnel/XHTTP servers or clients. Unknown profiles fail without fallback.
Connection workflow (design targets)
- Authorize: HTTPS POST validates supplied credentials and returns a random UUIDv4
session_id, a bearer token for one negotiation. Finalize within 120 seconds; never reuse it for another connection. - Resolve policy: report the explicit transport or probe eligible automatic candidates. Server restrictions, overrides, and pins win; corrections or rejections must be explicit and reported to the host.
- Check connectivity:
https://www.google.com/generate_204is a proposed general reachability signal, not proof of MEHS health. Filtering, DNS, captive portals, and policy can affect it. Pair it with authenticated server-path checks. - Probe: measure independent connections with multiple authenticated, nonce/request-ID-bound samples. Distinguish direct measurements from estimates. Use median RTT, robust jitter, loss, and enough transfer time/bytes for throughput.
- Choose and report: POST the selected mode and effective policy using the negotiation ID. Stability and loss matter more than peak throughput.
- Connect: automatic mode starts TCP and QUIC candidates concurrently, subject to server policy, with a 15-second setup window. One failed candidate is not server-wide failure while another path is healthy.
- Publish: distinguish a raw path ready to carry packets from a fully established selection workflow.
- Monitor: track path quality, keepalive, and health. A 30-second unhealthy-response interval triggers diagnostics; the design's terminal threshold is 15 consecutive seconds with no eligible server path, not a grace period extended by the health interval. Packaged-client reconnect behavior is specified in the CLI guide.
- Cache: retain selection for up to 24 hours, keyed to static configuration and effective policy. Invalidate on credentials, trust, configuration, policy, protocol, or transport-availability changes. A cache hit skips the full startup benchmark, never health monitoring or failure recovery.
Migration and delivery
Keep the active path while establishing and authenticating the candidate. Start new traffic on the candidate only when ready; continue draining the old path. A packet is delivered only after a MEHS acknowledgement. Retransmit unacknowledged data with stable per-direction sequence IDs; receivers deduplicate and reorder it.
Drain for at most 60 seconds. Move outstanding data before retiring the old path. If migration fails while TCP is still open, cancel the close timer and roll back. If no path remains, report failure and apply documented recovery policy. UDP-like traffic needs an explicit delivery policy; arbitrary retransmission must not duplicate externally visible datagrams. See transport migration and protocol reliability and bounds.
Configuration
Client JSON is strict schema 1: unknown fields are rejected, every accepted setting is applied, and
startup
validates the file. Configuration is immutable until disconnect/reconnect. Server policy always wins.
is_hot_change_available controls only live TCP/QUIC migration, not arbitrary configuration
reloads.
See the authoritative reference and
client example.
mode:auto,tcp_tls, orquic.client_mode:proxyortun;tunholds interface settings.tcp_connection_count/udp_connection_count: 0-32 independently per carrier. Zero disables a pool; maximum 64 data connections, plus one temporary control connection (65 during startup). HTTP profiles share these pools.- Setup/unreachable thresholds: 15 seconds. Keepalive: 15 seconds. Health check: 30 seconds.
- Migration drain: 60 seconds; cooldown, selection hysteresis, cache lifetime, negotiation TTL, frame and buffer bounds are configurable.
Recommended starting configurations
These are starting profiles, not measured universal optima. Validate against server policy and target networks.
| Profile | Mode / pool count | Health / keepalive | Drain | Use |
|---|---|---|---|---|
| Balanced | auto, 2 per carrier |
30 / 15 s | 60 s | Everyday use. |
| Latency-sensitive | auto, 2-3 per carrier |
15-20 / 10 s | 20-30 s | Games and SSH; higher overhead. |
| Bandwidth-focused | auto, 3-4 per carrier |
30 / 15-20 s | 60 s | Benchmark-driven throughput. |
| TCP-only | tcp_tls, TCP 1 / UDP 0 |
30 / 15 s | Not applicable | Blocked or degraded QUIC. |
| QUIC-pinned | quic, 1 QUIC |
20-30 / 15 s | Not applicable | Known reliable QUIC path. |
More connections cost sockets, memory, probes, and server load; they do not automatically improve performance. Prevent flapping with sustained improvement thresholds and cooldowns. Static changes require a reconnect; the 24-hour cache must not suppress recovery after network changes. Keep credentials and trust material out of logs and treat the negotiation ID as short-lived, not the running tunnel's long-term identity.
Architecture and responsibilities
Application / OS adapter
configuration + status
|
MEHS core
Protocol -- Session -- Transport manager
Framing Delivery TCP/TLS / QUIC
|
authenticated logical session
|
Server / API
Protocol processing owns frame types, lengths, IDs, ACKs, version checks, negotiation, and errors. Session handling owns authorization, expiry, replay protection, delivery, reconnect, and migration. Transport management owns probes, policy, candidate creation, rollback, and drain. Server policy centrally restricts modes, overrides, and resources. Host adapters own OS-specific proxy/VPN integration. The older raw-IP packet bridge requires a remote gateway; the current TUN flow model does not.
Supported now and not yet
Maintainer-verified: TLS/TCP and QUIC; all three MEHS HTTP profiles; automatic selection and live migration; multiple links and failover; SOCKS5 CONNECT/UDP ASSOCIATE; HTTP CONNECT; remote DNS; Linux TUN over both carriers with route cleanup after forced termination; Windows TUN and proxy; Android arm64 proxy; automatic reconnect; multi-hour keepalive sessions.
Available but not runtime-verified: macOS TUN, Android host-descriptor TUN, and iOS Network Extension packet flow. Verification is feature-specific, not a promise for every device. Consult the support matrix.
Out of scope: third-party TrustTunnel/XHTTP wire compatibility and per-app routing on macOS, iOS, or Android TUN. Open assurance gaps: no independent security audit or stable cross-release wire guarantee.
Security notes
- Use established cryptography and TLS 1.3 only; no downgrade to TLS 1.1/1.2.
- A returned public key does not authenticate a server: verify preconfigured trust and proof of possession bound to the session.
- Probe shape does not replace authentication, integrity, replay protection, or state validation.
- Session IDs must be unguessable, scoped, expiring, revocable bearer credentials protected against replay.
- Bound queues, buffers, frames, connections, and probe work. Reliability has resource and outage limits.
External HTTP(S) authorization
Set external_auth_url to delegate login checks to a trusted service. The server sends JSON
POST fields
username, password, and package version. Require a response like
{"authorized": true, "username": "canonical-user"}; both fields are mandatory even on
denial and extra fields are rejected.
The returned name becomes the account identity; the submitted name stays bound to the data-channel
handshake.
{
"external_auth_url": "https://auth.example.com/mehs/authorize"
}
The complete server configuration still needs listeners, certificate/key paths, and policy.
Local clients may be omitted when external authorization is enabled. Passwords remain only
in session memory,
not the local credential store. Use HTTPS: HTTP sends passwords without transport encryption.
See the frozen
authorization contract
for denial responses, HTTP behavior, timeouts, and limits.