engine update

This commit is contained in:
2026-03-20 17:26:47 +07:00
parent e234bd4006
commit 5aed291375
4 changed files with 90 additions and 21 deletions
+61 -11
View File
@@ -115,7 +115,7 @@ impl ClientHandler {
let ch = conn
.codec
.make_client_handshake(&BrowserProfile::CHROME_131, "google.com")
.make_client_handshake(&BrowserProfile::CHROME_131, "ubuntu.com")
.map_err(|e| format!("{:?}", e))?;
conn.outbound
.write_all(&ch)
@@ -257,6 +257,26 @@ pub struct ServerHandler {
pub token: CancellationToken,
}
impl ServerHandler {
async fn handle_fallback(outbound: &mut OwnedWriteHalf) {
// Формируем правдоподобный HTTP-ответ.
// Заголовок "Server: nginx" помогает мимикрировать под обычный веб-сервер.
let fallback_response = "HTTP/1.1 302 Found\r\n\
Server: nginx/1.18.0 (Ubuntu)\r\n\
Location: https://www.ubuntu.com/\r\n\
Content-Length: 0\r\n\
Connection: close\r\n\
\r\n";
// Пытаемся отправить ответ сканеру/цензору, игнорируя ошибки (если он уже отключился)
let _ = outbound.write_all(fallback_response.as_bytes()).await;
let _ = outbound.flush().await;
// Корректно закрываем соединение (отправляем FIN/RST)
let _ = outbound.shutdown().await;
}
}
#[async_trait::async_trait]
impl TunnelHandler for ServerHandler {
async fn run(mut self) -> Result<(), String> {
@@ -264,6 +284,9 @@ impl TunnelHandler for ServerHandler {
let (mux_tx, mux_rx) = mpsc::channel(BUF_SIZE);
let muxer = Muxer::new(mux_tx, false);
// Тайм-аут для защиты от "сканеров-молчунов" (Active Probing)
let handshake_timeout = std::time::Duration::from_secs(5);
let hello = loop {
match self
.conn
@@ -272,21 +295,47 @@ impl TunnelHandler for ServerHandler {
{
Ok(b) => break b,
Err(e) if e.action == ErrorAction::Wait => {
if self
.conn
.inbound
.read_buf(&mut self.conn.read_buf)
.await
.map_err(|e| e.to_string())?
== 0
{
return Err("Closed".into());
// Используем timeout: если за 5 сек не пришел полный handshake - рвем/фолбечим
let read_res = tokio::time::timeout(
handshake_timeout,
self.conn.inbound.read_buf(&mut self.conn.read_buf),
)
.await;
match read_res {
Ok(Ok(n)) if n == 0 => {
return Err("Client closed connection before handshake".into());
}
Ok(Ok(_)) => {
// Прочитали кусок, идем на следующий круг проверять handshake
continue;
}
Ok(Err(e)) => {
return Err(format!("Socket read error: {}", e));
}
Err(_) => {
// СРАБОТАЛ ТАЙМ-АУТ
netrunner_logger::warn!(
"Handshake timeout (Scanner detected). Triggering fallback."
);
ServerHandler::handle_fallback(&mut self.conn.outbound).await;
return Ok(()); // Выходим без ошибки, чтобы не крашить сервер
}
}
}
Err(e) => return Err(format!("{:?}", e)),
Err(e) => {
// ПРИШЕЛ МУСОР ИЛИ НЕВЕРНЫЙ ФОРМАТ (HTTP сканер)
netrunner_logger::warn!(
error = ?e,
"Invalid handshake format (Scanner detected). Triggering fallback."
);
ServerHandler::handle_fallback(&mut self.conn.outbound).await;
return Ok(()); // Выходим без ошибки
}
}
};
// --- ЕСЛИ МЫ ЗДЕСЬ, ХЕНДШЕЙК ПРОШЕЛ УСПЕШНО ---
self.conn
.outbound
.write_all(&hello)
@@ -294,6 +343,7 @@ impl TunnelHandler for ServerHandler {
.map_err(|e| e.to_string())?;
let handler = std::sync::Arc::new(StreamHandler::new(muxer, ConnectionRole::Server));
TunnelEngine {
inbound: self.conn.inbound,
outbound: self.conn.outbound,
+12 -3
View File
@@ -50,8 +50,8 @@ impl TunnelEngine {
}
_ = heartbeat.tick() => {
let msg = MuxMessage { stream_id: 0, frame_type: FrameType::Heartbeat, data: Bytes::new() };
Self::handle_outbound(&mut outbound, &mut codec, msg).await?;
let msg = MuxMessage { stream_id: 0, frame_type: FrameType::Heartbeat, data: Bytes::new() };
Self::handle_outbound(&mut outbound, &mut codec, msg).await?;
}
msg_opt = mux_rx.recv() => {
@@ -78,7 +78,7 @@ impl TunnelEngine {
.map_err(|e| e.to_string())?;
if n == 0 && read_buf.is_empty() {
netrunner_logger::error!("Connection closed by peer (EOF detected)");
netrunner_logger::info!("Connection closed by peer (EOF detected)");
return Err("EOF".into());
}
@@ -95,6 +95,15 @@ impl TunnelEngine {
break;
}
if e.action == ErrorAction::Drop {
// ТСПУ подмешал мусор ИЛИ ключи не совпали.
// Мгновенный выход с ошибкой приведет к обрыву TCP-соединения.
netrunner_logger::error!(
"CRITICAL: Crypto tampering or sync lost. Hard dropping tunnel!"
);
return Err("Crypto drop".into());
}
error!(error = ?e, "Codec inbound failed");
return Err(format!("Codec error: {:?}", e));
}