Revert "v0.3.1: IP-literal destinations -> plain TCP passthrough (always)"

This reverts commit eed64caf87.
This commit is contained in:
therealaleph
2026-04-21 21:15:07 +03:00
parent eed64caf87
commit c694073da8
4 changed files with 5 additions and 25 deletions
Generated
+1 -1
View File
@@ -365,7 +365,7 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]] [[package]]
name = "mhrv-rs" name = "mhrv-rs"
version = "0.3.1" version = "0.3.0"
dependencies = [ dependencies = [
"base64", "base64",
"bytes", "bytes",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "mhrv-rs" name = "mhrv-rs"
version = "0.3.1" version = "0.3.0"
edition = "2021" edition = "2021"
description = "Rust port of MasterHttpRelayVPN -- DPI bypass via Google Apps Script relay with domain fronting" description = "Rust port of MasterHttpRelayVPN -- DPI bypass via Google Apps Script relay with domain fronting"
license = "MIT" license = "MIT"
+2 -5
View File
@@ -318,15 +318,12 @@ impl DomainFronter {
Ok(Ok(bytes)) => bytes, Ok(Ok(bytes)) => bytes,
Ok(Err(e)) => { Ok(Err(e)) => {
self.relay_failures.fetch_add(1, Ordering::Relaxed); self.relay_failures.fetch_add(1, Ordering::Relaxed);
// Most upstream errors (self-signed certs, unreachable hosts, tracing::error!("Relay failed: {}", e);
// non-HTTP endpoints) are normal for misrouted traffic. Log
// at warn so they don't spam error channels.
tracing::warn!("relay failed: {}", e);
return error_response(502, &format!("Relay error: {}", e)); return error_response(502, &format!("Relay error: {}", e));
} }
Err(_) => { Err(_) => {
self.relay_failures.fetch_add(1, Ordering::Relaxed); self.relay_failures.fetch_add(1, Ordering::Relaxed);
tracing::warn!("relay timeout"); tracing::error!("Relay timeout");
return error_response(504, "Relay timeout"); return error_response(504, "Relay timeout");
} }
}; };
+1 -18
View File
@@ -308,17 +308,7 @@ async fn dispatch_tunnel(
return do_sni_rewrite_tunnel_from_tcp(sock, &host, port, mitm, rewrite_ctx).await; return do_sni_rewrite_tunnel_from_tcp(sock, &host, port, mitm, rewrite_ctx).await;
} }
// 2. IP-literal destinations are almost always app-level custom protocols // 2. Peek at the first byte to detect TLS vs plain. Time-bounded — if the
// (xray/VLESS, torrent, SSH, VPN, raw TCP). Browsers never use raw IPs
// in CONNECT. MITMing these would break the app's own TLS/auth, and
// trying to relay opaque bytes through Apps Script always fails.
// Always plain TCP passthrough for IP literals.
if is_ip_literal(&host) {
plain_tcp_passthrough(sock, &host, port).await;
return Ok(());
}
// 3. Peek at the first byte to detect TLS vs plain. Time-bounded — if the
// client doesn't send anything within 300ms, assume server-first // client doesn't send anything within 300ms, assume server-first
// protocol (SMTP, POP3, FTP banner) and jump straight to plain TCP. // protocol (SMTP, POP3, FTP banner) and jump straight to plain TCP.
let mut peek_buf = [0u8; 8]; let mut peek_buf = [0u8; 8];
@@ -355,13 +345,6 @@ async fn dispatch_tunnel(
Ok(()) Ok(())
} }
// ---------- IP literal detection ----------
fn is_ip_literal(host: &str) -> bool {
let h = host.trim_start_matches('[').trim_end_matches(']');
h.parse::<std::net::IpAddr>().is_ok()
}
// ---------- Plain TCP passthrough ---------- // ---------- Plain TCP passthrough ----------
async fn plain_tcp_passthrough(mut sock: TcpStream, host: &str, port: u16) { async fn plain_tcp_passthrough(mut sock: TcpStream, host: &str, port: u16) {