nice buf sizes and moved duration in consts
This commit is contained in:
@@ -7,8 +7,6 @@ pub static GLOBAL_NET_CONFIG: OnceLock<NetworkConfig> = OnceLock::new();
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NetworkConfig {
|
||||
pub mtu: usize,
|
||||
pub max_wire_frame_size: usize,
|
||||
pub safe_payload_size: usize,
|
||||
|
||||
pub tcp_buffer_size: usize,
|
||||
pub udp_buffer_size: usize,
|
||||
@@ -29,17 +27,11 @@ pub struct NetworkConfig {
|
||||
}
|
||||
impl NetworkConfig {
|
||||
pub fn new(system_mtu: usize) -> Self {
|
||||
let transport_overhead = 48;
|
||||
let max_wire_frame = system_mtu.saturating_sub(transport_overhead);
|
||||
let safe_payload = max_wire_frame.saturating_sub(64);
|
||||
|
||||
let chunk_size = 16 * 1024;
|
||||
let heavy_buf = 256 * 1024;
|
||||
|
||||
Self {
|
||||
mtu: system_mtu,
|
||||
max_wire_frame_size: max_wire_frame,
|
||||
safe_payload_size: safe_payload,
|
||||
|
||||
tcp_buffer_size: 8 * 1024,
|
||||
udp_buffer_size: 64 * 1024,
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::net::connection::muxer::{MuxMessage, Muxer};
|
||||
use crate::net::NetworkConfig;
|
||||
use crate::net::{NetworkConfig, BRIDGE_IDLE_TIMEOUT};
|
||||
use crate::nrxp::FrameType;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use netrunner_logger::{debug, error, info, warn};
|
||||
@@ -10,8 +10,6 @@ use tokio::net::UdpSocket;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::time::timeout;
|
||||
|
||||
const IDLE_TIMEOUT: Duration = Duration::from_secs(300);
|
||||
|
||||
struct StreamGuard {
|
||||
stream_id: u32,
|
||||
muxer: Arc<Muxer>,
|
||||
@@ -43,7 +41,7 @@ pub(crate) async fn run_tcp_bridge<R, W>(
|
||||
|
||||
loop {
|
||||
buf.reserve(NetworkConfig::global().tcp_buffer_size);
|
||||
let select_res = timeout(IDLE_TIMEOUT, async {
|
||||
let select_res = timeout(BRIDGE_IDLE_TIMEOUT, async {
|
||||
tokio::select! {
|
||||
|
||||
res = reader.read_buf(&mut buf) => {
|
||||
@@ -132,7 +130,7 @@ pub(crate) async fn run_udp_bridge(
|
||||
info!(stream_id, "🌉 UDP Bridge active");
|
||||
|
||||
loop {
|
||||
let select_res = timeout(IDLE_TIMEOUT, async {
|
||||
let select_res = timeout(BRIDGE_IDLE_TIMEOUT, async {
|
||||
tokio::select! {
|
||||
|
||||
res = socket.recv(&mut buf) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{net::Ipv4Addr, sync::Arc, time::Duration};
|
||||
use std::{net::Ipv4Addr, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
net::{
|
||||
@@ -7,7 +7,8 @@ use crate::{
|
||||
handler::{RemoteOpener, StreamHandler},
|
||||
muxer::Muxer,
|
||||
},
|
||||
NetworkConfig,
|
||||
NetworkConfig, FALLBACK_CONNECT_TIMEOUT, LEG_RECONNECT_DELAY, LEG_STAGGER_DELAY,
|
||||
MAX_TUNNEL_LEGS, SECURE_HANDSHAKE_TIMEOUT, TLS_HELLO_TIMEOUT, TOPOLOGY_PRINT_INTERVAL,
|
||||
},
|
||||
nrxp::{Codec, ErrorAction, Frame, FrameType},
|
||||
rawcast::{LocalProtocol, RawCastAdapter, RawCastFrame},
|
||||
@@ -200,17 +201,17 @@ impl ClientHandler {
|
||||
|
||||
info!("🚀 Netrunner Multi-Path Tunnel Initializing (10 Legs max).");
|
||||
|
||||
for id in 0..10 {
|
||||
for id in 0..MAX_TUNNEL_LEGS {
|
||||
let addr = remote_proxy_addr.to_string();
|
||||
let m = muxer.clone();
|
||||
let sid = session_id.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(id as u64 * 250)).await;
|
||||
tokio::time::sleep(LEG_STAGGER_DELAY * id).await;
|
||||
loop {
|
||||
if let Err(e) = Self::establish_leg(&addr, id, m.clone(), &sid).await {
|
||||
error!("Leg {} disconnected: {}. Reconnecting in 3s...", id, e);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
|
||||
tokio::time::sleep(LEG_RECONNECT_DELAY).await;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -219,7 +220,7 @@ impl ClientHandler {
|
||||
let m_weak = Arc::downgrade(&muxer);
|
||||
tokio::spawn(async move {
|
||||
while let Some(m_stats) = m_weak.upgrade() {
|
||||
tokio::time::sleep(Duration::from_secs(15)).await;
|
||||
tokio::time::sleep(TOPOLOGY_PRINT_INTERVAL).await;
|
||||
if m_stats.active_legs_count() == 0 {
|
||||
break;
|
||||
}
|
||||
@@ -362,11 +363,8 @@ impl ServerHandler {
|
||||
let target_host = "ubuntu.com:443";
|
||||
info!(target = %target_host, "Stealth fallback: bridging to Target");
|
||||
|
||||
let target_stream = tokio::time::timeout(
|
||||
std::time::Duration::from_secs(3),
|
||||
TcpStream::connect(target_host),
|
||||
)
|
||||
.await;
|
||||
let target_stream =
|
||||
tokio::time::timeout(FALLBACK_CONNECT_TIMEOUT, TcpStream::connect(target_host)).await;
|
||||
|
||||
match target_stream {
|
||||
Ok(Ok(target_server)) => {
|
||||
@@ -406,8 +404,6 @@ impl TunnelHandler for ServerHandler {
|
||||
async fn run(mut self) -> Result<(), String> {
|
||||
info!("Acting as TLS Server with Stealth Fallback");
|
||||
|
||||
let handshake_timeout = std::time::Duration::from_secs(1);
|
||||
|
||||
let hello = loop {
|
||||
let buf_snapshot = self.conn.read_buf.clone().freeze();
|
||||
match self
|
||||
@@ -419,7 +415,7 @@ impl TunnelHandler for ServerHandler {
|
||||
Err(e) => match e.execute_strategy() {
|
||||
ErrorAction::Wait => {
|
||||
let res = tokio::time::timeout(
|
||||
handshake_timeout,
|
||||
TLS_HELLO_TIMEOUT,
|
||||
self.conn.inbound.read_buf(&mut self.conn.read_buf),
|
||||
)
|
||||
.await;
|
||||
@@ -462,7 +458,7 @@ impl TunnelHandler for ServerHandler {
|
||||
|
||||
let (session_id, leg_id) = loop {
|
||||
let n = tokio::time::timeout(
|
||||
std::time::Duration::from_secs(3),
|
||||
SECURE_HANDSHAKE_TIMEOUT,
|
||||
self.conn.inbound.read_buf(&mut self.conn.read_buf),
|
||||
)
|
||||
.await
|
||||
@@ -527,7 +523,7 @@ impl TunnelHandler for ServerHandler {
|
||||
let m_weak = Arc::downgrade(&muxer);
|
||||
tokio::spawn(async move {
|
||||
while let Some(m_stats) = m_weak.upgrade() {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(15)).await;
|
||||
tokio::time::sleep(TOPOLOGY_PRINT_INTERVAL).await;
|
||||
if m_stats.active_legs_count() == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use tokio_util::sync::CancellationToken;
|
||||
use crate::{
|
||||
net::{
|
||||
connection::{handler::StreamHandler, muxer::MuxMessage},
|
||||
NetworkConfig,
|
||||
NetworkConfig, HEALTH_CHECK_INTERVAL,
|
||||
},
|
||||
nrxp::{Codec, ErrorAction, FrameType},
|
||||
};
|
||||
@@ -114,7 +114,7 @@ impl TunnelEngine {
|
||||
let mut outbound = outbound;
|
||||
let mut control_rx = control_rx;
|
||||
let mut data_rx = data_rx;
|
||||
let mut heartbeat = tokio::time::interval(std::time::Duration::from_secs(15));
|
||||
let mut heartbeat = tokio::time::interval(HEALTH_CHECK_INTERVAL);
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
|
||||
@@ -3,9 +3,10 @@ use dashmap::DashMap;
|
||||
use netrunner_logger::{debug, info, warn};
|
||||
use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::mpsc::error::TrySendError;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
// Подключаем твои константы (убедись, что путь импорта совпадает с твоей структурой)
|
||||
use crate::net::constants::{HEALTH_CHECK_TIMEOUT, MAX_TUNNEL_LEGS, MUXER_POOL_SIZE};
|
||||
use crate::nrxp::FrameType;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
@@ -13,6 +14,7 @@ pub struct LegStats {
|
||||
pub tx_bytes: AtomicU64,
|
||||
pub rx_bytes: AtomicU64,
|
||||
pub rtt_ms: AtomicU32,
|
||||
pub strikes: AtomicU32, // 👈 Счетчик пропущенных пингов (страйков)
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
@@ -58,6 +60,7 @@ pub struct Muxer {
|
||||
id_gen: Arc<IdGenerator>,
|
||||
session_id: Arc<String>,
|
||||
}
|
||||
|
||||
impl Muxer {
|
||||
pub fn new(is_client: bool, session_id: String) -> Self {
|
||||
Self {
|
||||
@@ -74,11 +77,9 @@ impl Muxer {
|
||||
control_tx: Sender<MuxMessage>,
|
||||
data_tx: Sender<MuxMessage>,
|
||||
) {
|
||||
if self.legs.len() >= 10 {
|
||||
warn!(
|
||||
leg_id,
|
||||
"MUXER: Maximum of 10 legs reached. Ignoring new leg."
|
||||
);
|
||||
// 👈 Используем константу вместо магической 10
|
||||
if self.legs.len() >= MAX_TUNNEL_LEGS as usize {
|
||||
warn!(leg_id, "MUXER: Max legs reached: {}", MAX_TUNNEL_LEGS);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -124,6 +125,7 @@ impl Muxer {
|
||||
.collect();
|
||||
}
|
||||
|
||||
// Выбираем ноги с наименьшим RTT (ноги со страйками = 5000ms будут в конце)
|
||||
candidates.sort_by_key(|(_, leg)| {
|
||||
let rtt = leg.stats.rtt_ms.load(Ordering::Relaxed);
|
||||
if rtt == 0 {
|
||||
@@ -133,7 +135,8 @@ impl Muxer {
|
||||
}
|
||||
});
|
||||
|
||||
let pool_size = std::cmp::min(candidates.len(), 2);
|
||||
// 👈 Используем константу
|
||||
let pool_size = std::cmp::min(candidates.len(), MUXER_POOL_SIZE);
|
||||
let target = &candidates[stream_id as usize % pool_size];
|
||||
|
||||
Some(target.clone())
|
||||
@@ -244,6 +247,7 @@ impl Muxer {
|
||||
self.id_gen.next()
|
||||
}
|
||||
|
||||
// 👈 Полностью переписанный параллельный Health Check со страйками
|
||||
pub async fn perform_health_check(&self) {
|
||||
let legs: Vec<(u32, Sender<MuxMessage>)> = self
|
||||
.legs
|
||||
@@ -251,40 +255,67 @@ impl Muxer {
|
||||
.map(|k| (*k.key(), k.value().control_tx.clone()))
|
||||
.collect();
|
||||
|
||||
// Запускаем проверку каждой ноги параллельно
|
||||
for (leg_id, tx) in legs {
|
||||
let probe_stream_id = self.id_gen.next();
|
||||
let (probe_tx, mut probe_rx) = tokio::sync::mpsc::channel(2);
|
||||
let muxer = self.clone(); // Дешевое клонирование (внутри Arc)
|
||||
|
||||
self.register_stream(probe_stream_id, probe_tx);
|
||||
tokio::spawn(async move {
|
||||
let probe_stream_id = muxer.id_gen.next();
|
||||
let (probe_tx, mut probe_rx) = tokio::sync::mpsc::channel(2);
|
||||
|
||||
let msg = MuxMessage {
|
||||
stream_id: probe_stream_id,
|
||||
frame_type: FrameType::Handshake,
|
||||
data: Bytes::from("PING"),
|
||||
};
|
||||
muxer.register_stream(probe_stream_id, probe_tx);
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
let msg = MuxMessage {
|
||||
stream_id: probe_stream_id,
|
||||
frame_type: FrameType::Handshake,
|
||||
data: Bytes::from("PING"),
|
||||
};
|
||||
|
||||
if tx.try_send(msg).is_ok() {
|
||||
match tokio::time::timeout(std::time::Duration::from_secs(2), probe_rx.recv()).await
|
||||
{
|
||||
Ok(Some(_)) => {
|
||||
let rtt = start.elapsed().as_millis() as u32;
|
||||
if let Some(leg) = self.legs.get(&leg_id) {
|
||||
leg.stats.rtt_ms.store(rtt, Ordering::Relaxed);
|
||||
debug!(leg_id, rtt, "✅ Leg Health Check OK");
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
if tx.try_send(msg).is_ok() {
|
||||
// Используем новую константу таймаута
|
||||
match tokio::time::timeout(HEALTH_CHECK_TIMEOUT, probe_rx.recv()).await {
|
||||
Ok(Some(_)) => {
|
||||
let rtt = start.elapsed().as_millis() as u32;
|
||||
if let Some(leg) = muxer.legs.get(&leg_id) {
|
||||
// Пинг прошел: обновляем RTT и СБРАСЫВАЕМ страйки
|
||||
leg.stats.rtt_ms.store(rtt, Ordering::Relaxed);
|
||||
leg.stats.strikes.store(0, Ordering::Relaxed);
|
||||
debug!(leg_id, rtt, "✅ Leg Health Check OK");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Пинг провален: увеличиваем страйки
|
||||
if let Some(leg) = muxer.legs.get(&leg_id) {
|
||||
let strikes = leg.stats.strikes.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
|
||||
if strikes >= 3 {
|
||||
// 3 промаха = смерть. Балансировщик перестанет кидать сюда трафик
|
||||
leg.stats.rtt_ms.store(5000, Ordering::Relaxed);
|
||||
warn!(
|
||||
leg_id,
|
||||
strikes, "❌ Leg DEAD (3 strikes). RTT set to 5000."
|
||||
);
|
||||
} else {
|
||||
// 1-2 промаха: ждем, возможно это радио-пауза в мобильной сети
|
||||
warn!(
|
||||
leg_id,
|
||||
strikes, "⚠️ Leg missed ping. Strike {}/3", strikes
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if let Some(leg) = self.legs.get(&leg_id) {
|
||||
leg.stats.rtt_ms.store(5000, Ordering::Relaxed);
|
||||
warn!(leg_id, "❌ Leg Health Check Timeout (marked as slow)");
|
||||
}
|
||||
} else {
|
||||
// Если канал (mpsc) забит или закрыт, считаем ногу мертвой сразу
|
||||
if let Some(leg) = muxer.legs.get(&leg_id) {
|
||||
leg.stats.rtt_ms.store(5000, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.remove_stream(probe_stream_id);
|
||||
muxer.remove_stream(probe_stream_id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,6 +350,7 @@ impl Muxer {
|
||||
let tx = stats.tx_bytes.load(Ordering::Relaxed);
|
||||
let rx = stats.rx_bytes.load(Ordering::Relaxed);
|
||||
let rtt = stats.rtt_ms.load(Ordering::Relaxed);
|
||||
let strikes = stats.strikes.load(Ordering::Relaxed);
|
||||
|
||||
total_tx += tx;
|
||||
total_rx += rx;
|
||||
@@ -330,13 +362,23 @@ impl Muxer {
|
||||
format!("{}ms", rtt)
|
||||
};
|
||||
|
||||
// 👈 Добавлен визуальный статус ноги для отладки
|
||||
let status_icon = if strikes >= 3 {
|
||||
"💀"
|
||||
} else if strikes > 0 {
|
||||
"⚠️"
|
||||
} else {
|
||||
"✅"
|
||||
};
|
||||
|
||||
legs_info.push(format!(
|
||||
" ├─ Leg {} ({}) ─ ⇡ {:<9} | ⇣ {:<9} [RTT: {}]",
|
||||
" ├─ Leg {} ({}) ─ ⇡ {:<9} | ⇣ {:<9} [RTT: {:<6}] [Status: {}]",
|
||||
id,
|
||||
leg_type,
|
||||
Self::format_size(tx),
|
||||
Self::format_size(rx),
|
||||
rtt_str
|
||||
rtt_str,
|
||||
status_icon
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
use std::time::Duration;
|
||||
|
||||
// --- Лимиты системы ---
|
||||
pub const MAX_SOCKETS: usize = 2048; // Лимит сокетов в SocketSet (Anti-DDoS)
|
||||
pub const MAX_TUNNEL_LEGS: u32 = 10; // Максимальное кол-во физических соединений (Legs)
|
||||
pub const MUXER_POOL_SIZE: usize = 2; // Из скольких лучших Leg-ов выбирать для балансировки
|
||||
|
||||
// --- Таймауты ---
|
||||
pub const TCP_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(20); // Время на установку SYN/ACK
|
||||
pub const UDP_IDLE_TIMEOUT: Duration = Duration::from_secs(60); // Смерть UDP сессии без данных
|
||||
pub const GLOBAL_IDLE_TIMEOUT: Duration = Duration::from_secs(120); // Очистка Tracker-ом
|
||||
pub const HEALTH_CHECK_INTERVAL: Duration = Duration::from_secs(5); // Частота пинга Leg-ов
|
||||
pub const HEALTH_CHECK_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
pub const LEG_RECONNECT_DELAY: Duration = Duration::from_secs(5); // Пауза перед реконнектом Leg
|
||||
pub const BRIDGE_IDLE_TIMEOUT: Duration = Duration::from_secs(300); // Таймаут задач-бриджей
|
||||
|
||||
// --- Сетевые порты ---
|
||||
pub const DNS_PORT: u16 = 53;
|
||||
pub const HTTP_PORT: u16 = 80;
|
||||
pub const HTTPS_PORT: u16 = 443;
|
||||
pub const NETBIOS_PORTS: [u16; 2] = [137, 138];
|
||||
|
||||
// --- Критические оверхеды (для MTU/MSS) ---
|
||||
pub const IPV4_TCP_OVERHEAD: usize = 40; // IPv4(20) + TCP(20)
|
||||
pub const NRXP_OVERHEAD: usize = 254; // Запас под заголовки твоего протокола и TLS
|
||||
|
||||
// --- Настройки безопасности ---
|
||||
pub const AUTH_TIME_STEP: u64 = 60; // Шаг генерации токена (секунды)
|
||||
pub const AUTH_WINDOW_SIZE: u64 = 2; // Допуск шагов времени (current +/- 2)
|
||||
|
||||
// --- Настройки Multipath (Legs) ---
|
||||
pub const LEG_STAGGER_DELAY: Duration = Duration::from_millis(250);
|
||||
pub const TOPOLOGY_PRINT_INTERVAL: Duration = Duration::from_secs(15);
|
||||
|
||||
// --- Настройки Stealth Fallback (Маскировка) ---
|
||||
pub const STEALTH_FALLBACK_HOST: &str = "ubuntu.com:443";
|
||||
pub const FALLBACK_CONNECT_TIMEOUT: Duration = Duration::from_secs(3);
|
||||
|
||||
// --- Таймауты Handshake ---
|
||||
pub const TLS_HELLO_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
pub const SECURE_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(3);
|
||||
@@ -1,5 +1,7 @@
|
||||
mod config;
|
||||
mod connection;
|
||||
mod constants;
|
||||
|
||||
pub use config::NetworkConfig;
|
||||
pub use connection::{ClientHandler, Connection, ServerHandler, TunnelHandler};
|
||||
pub use constants::*;
|
||||
|
||||
Reference in New Issue
Block a user