fallback and address change
This commit is contained in:
+1
-1
@@ -32,7 +32,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
})
|
})
|
||||||
.expect("Failed to initialize TUN device");
|
.expect("Failed to initialize TUN device");
|
||||||
|
|
||||||
let remote_address: String = "62.60.244.156:443".into();
|
let remote_address: String = "147.45.43.70:443".into();
|
||||||
let _ = setup_platform_routing(&remote_address);
|
let _ = setup_platform_routing(&remote_address);
|
||||||
|
|
||||||
info!("TUN interface is UP: 10.0.0.1/24");
|
info!("TUN interface is UP: 10.0.0.1/24");
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ use crate::{
|
|||||||
},
|
},
|
||||||
tlseng::profile::BrowserProfile,
|
tlseng::profile::BrowserProfile,
|
||||||
};
|
};
|
||||||
use bytes::BytesMut;
|
use bytes::{Bytes, BytesMut};
|
||||||
use netrunner_logger::info;
|
use netrunner_logger::{info, warn};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{AsyncReadExt, AsyncWriteExt},
|
io::{AsyncReadExt, AsyncWriteExt},
|
||||||
net::{
|
net::{
|
||||||
@@ -260,35 +260,72 @@ pub struct ServerHandler {
|
|||||||
pub conn: Connection,
|
pub conn: Connection,
|
||||||
pub token: CancellationToken,
|
pub token: CancellationToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerHandler {
|
impl ServerHandler {
|
||||||
async fn handle_fallback(outbound: &mut OwnedWriteHalf) {
|
async fn handle_stealth_fallback(
|
||||||
let fallback_response = "HTTP/1.1 302 Found\r\n\
|
mut client_inbound: OwnedReadHalf,
|
||||||
Server: nginx/1.18.0 (Ubuntu)\r\n\
|
mut client_outbound: OwnedWriteHalf,
|
||||||
Location: https://www.ubuntu.com/\r\n\
|
initial_data: bytes::Bytes,
|
||||||
Content-Length: 0\r\n\
|
) {
|
||||||
Connection: close\r\n\
|
let target_host = "ubuntu.com:443";
|
||||||
\r\n";
|
info!(target = %target_host, "Stealth fallback: bridging to Target");
|
||||||
|
|
||||||
let _ = outbound.write_all(fallback_response.as_bytes()).await;
|
// 1. Пытаемся подключиться с коротким таймаутом
|
||||||
let _ = outbound.flush().await;
|
let target_stream = tokio::time::timeout(
|
||||||
let _ = outbound.shutdown().await;
|
std::time::Duration::from_secs(3),
|
||||||
|
TcpStream::connect(target_host),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match target_stream {
|
||||||
|
Ok(Ok(mut target_server)) => {
|
||||||
|
let (mut server_read, mut server_write) = target_server.into_split();
|
||||||
|
|
||||||
|
// 2. Скармливаем те байты, которые уже вычитали (Client Hello)
|
||||||
|
if !initial_data.is_empty() {
|
||||||
|
if let Err(e) = server_write.write_all(&initial_data).await {
|
||||||
|
warn!("Failed to push initial data to fallback: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Запускаем bidirectional copy
|
||||||
|
// Это создаст две задачи, которые будут перекачивать байты, пока одна сторона не закроется
|
||||||
|
let res = tokio::io::copy_bidirectional(
|
||||||
|
&mut tokio::io::join(&mut client_inbound, &mut client_outbound),
|
||||||
|
&mut tokio::io::join(&mut server_read, &mut server_write),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok((from_client, from_server)) => {
|
||||||
|
info!(
|
||||||
|
"Fallback closed. Sent: {} bytes, Recv: {} bytes",
|
||||||
|
from_client, from_server
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(e) => warn!("Fallback bridge error: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => warn!("Fallback connect error: {}", e),
|
||||||
|
Err(_) => warn!("Fallback connection timed out (Target unreachable)"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl TunnelHandler for ServerHandler {
|
impl TunnelHandler for ServerHandler {
|
||||||
async fn run(mut self) -> Result<(), String> {
|
async fn run(mut self) -> Result<(), String> {
|
||||||
info!("Acting as TLS Server");
|
info!("Acting as TLS Server with Stealth Fallback");
|
||||||
|
|
||||||
// --- ИЗМЕНЕНИЕ ДЛЯ НОВОГО MUXER ---
|
|
||||||
let (control_tx, control_rx) = mpsc::channel(MESSAGE_CHANNEL_SIZE);
|
let (control_tx, control_rx) = mpsc::channel(MESSAGE_CHANNEL_SIZE);
|
||||||
let (data_tx, data_rx) = mpsc::channel(MESSAGE_CHANNEL_SIZE);
|
let (data_tx, data_rx) = mpsc::channel(MESSAGE_CHANNEL_SIZE);
|
||||||
let muxer = Muxer::new(control_tx, data_tx, false);
|
let muxer = Muxer::new(control_tx, data_tx, false);
|
||||||
|
|
||||||
let handshake_timeout = std::time::Duration::from_secs(5);
|
let handshake_timeout = std::time::Duration::from_secs(1);
|
||||||
|
|
||||||
let hello = loop {
|
let hello = loop {
|
||||||
|
let buf_snapshot = self.conn.read_buf.clone().freeze();
|
||||||
|
|
||||||
match self
|
match self
|
||||||
.conn
|
.conn
|
||||||
.codec
|
.codec
|
||||||
@@ -303,35 +340,42 @@ impl TunnelHandler for ServerHandler {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
match read_res {
|
match read_res {
|
||||||
Ok(Ok(n)) if n == 0 => {
|
Ok(Ok(n)) if n == 0 => return Err("Client closed".into()),
|
||||||
return Err("Client closed connection before handshake".into());
|
Ok(Ok(_)) => continue,
|
||||||
}
|
Ok(Err(e)) => return Err(e.to_string()),
|
||||||
Ok(Ok(_)) => {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Ok(Err(e)) => {
|
|
||||||
return Err(format!("Socket read error: {}", e));
|
|
||||||
}
|
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
netrunner_logger::warn!(
|
warn!("Handshake timeout. Going stealth.");
|
||||||
"Handshake timeout (Scanner detected). Triggering fallback."
|
// Используем наш снимок, так как основной буфер мог быть частично съеден
|
||||||
);
|
ServerHandler::handle_stealth_fallback(
|
||||||
ServerHandler::handle_fallback(&mut self.conn.outbound).await;
|
self.conn.inbound,
|
||||||
|
self.conn.outbound,
|
||||||
|
buf_snapshot,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
netrunner_logger::warn!(
|
warn!("Auth/Format failed: {:?}. Going stealth.", e);
|
||||||
error = ?e,
|
// ВАЖНО: используем сохраненный buf_snapshot
|
||||||
"Invalid handshake format (Scanner detected). Triggering fallback."
|
info!(
|
||||||
|
"DEBUG: Restoring {} bytes from snapshot for fallback",
|
||||||
|
buf_snapshot.len()
|
||||||
);
|
);
|
||||||
ServerHandler::handle_fallback(&mut self.conn.outbound).await;
|
|
||||||
|
ServerHandler::handle_stealth_fallback(
|
||||||
|
self.conn.inbound,
|
||||||
|
self.conn.outbound,
|
||||||
|
buf_snapshot,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Если дошли сюда — значит это наш клиент, шлем Server Hello
|
||||||
self.conn
|
self.conn
|
||||||
.outbound
|
.outbound
|
||||||
.write_all(&hello)
|
.write_all(&hello)
|
||||||
@@ -345,8 +389,8 @@ impl TunnelHandler for ServerHandler {
|
|||||||
outbound: self.conn.outbound,
|
outbound: self.conn.outbound,
|
||||||
codec: self.conn.codec,
|
codec: self.conn.codec,
|
||||||
read_buf: self.conn.read_buf,
|
read_buf: self.conn.read_buf,
|
||||||
control_rx, // Передаем оба ресивера в Engine
|
control_rx,
|
||||||
data_rx, // Передаем оба ресивера в Engine
|
data_rx,
|
||||||
handler,
|
handler,
|
||||||
token: self.token,
|
token: self.token,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user