comments remove
This commit is contained in:
@@ -40,10 +40,10 @@ impl DnsHandler {
|
||||
|
||||
if needs_update {
|
||||
let p_clone = self.cache_path.clone();
|
||||
// Просто спавним асинхронную задачу
|
||||
|
||||
tokio::spawn(async move {
|
||||
tokio::time::sleep(Duration::from_secs(10)).await;
|
||||
// Теперь вызываем асинхронно через .await
|
||||
|
||||
if let Err(e) = Self::download_blocklist_async(p_clone).await {
|
||||
netrunner_logger::error!("DNS: Background update failed: {}", e);
|
||||
}
|
||||
@@ -53,7 +53,6 @@ impl DnsHandler {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Делаем функцию асинхронной и убираем block_on
|
||||
async fn download_blocklist_async(cache_path: String) -> anyhow::Result<()> {
|
||||
info!("DNS: Starting background download to {}", cache_path);
|
||||
|
||||
@@ -112,7 +111,6 @@ impl DnsHandler {
|
||||
.set_recursion_available(true)
|
||||
.add_query(query.clone());
|
||||
|
||||
// Проверка блокировок
|
||||
if self.forbidden_suffixes.iter().any(|s| name.ends_with(s))
|
||||
|| self.block_list.contains(&name)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::connections::dns::DnsHandler; // проверь путь
|
||||
use crate::connections::dns::DnsHandler;
|
||||
use crate::connections::ip_store::FakeIpStore;
|
||||
use smoltcp::socket::udp;
|
||||
|
||||
|
||||
@@ -14,18 +14,14 @@ use tokio_util::sync::CancellationToken;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// 1. Инициализация логгера (теперь он внутри асинхронного контекста)
|
||||
netrunner_logger::Logger::init();
|
||||
info!("Initializing NetRunner Stack...");
|
||||
|
||||
// 2. Инициализация DNS асинхронно
|
||||
// Передаем пустую строку или путь к кэшу (на десктопе можно ".")
|
||||
let mut dns_handler = DnsHandler::new(".");
|
||||
if let Err(e) = dns_handler.init().await {
|
||||
error!("Failed to initialize DNS blocklist: {}", e);
|
||||
}
|
||||
|
||||
// 3. Настройка TUN устройства
|
||||
let tun_device = Tun::create(|config| {
|
||||
config
|
||||
.tun_name("netr0")
|
||||
@@ -41,7 +37,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
info!("TUN interface is UP: 10.0.0.1/24");
|
||||
|
||||
// 4. Конфигурация стека протоколов (MTU 1280 для стабильности)
|
||||
let config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
||||
let mut caps = DeviceCapabilities::default();
|
||||
caps.max_transmission_unit = 1280;
|
||||
@@ -56,7 +51,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
let proxy_ip = network.get_self_local_address();
|
||||
|
||||
// 5. Запуск сетевого прокси в отдельной задаче
|
||||
let network_token = CancellationToken::new();
|
||||
let net_token_for_spawn = network_token.clone();
|
||||
tokio::spawn(async move {
|
||||
@@ -64,7 +58,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
network.run(net_token_for_spawn).await;
|
||||
});
|
||||
|
||||
// 6. Инициализация Engine
|
||||
let mut engine = Engine::new(config, caps, proxy_ip, dns_handler);
|
||||
engine.set_any_ip(true);
|
||||
engine.set_transparent_mode();
|
||||
@@ -84,7 +77,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Очистка ресурсов
|
||||
network_token.cancel();
|
||||
info!("Restoring system routing...");
|
||||
let addr: std::net::SocketAddr = remote_address.parse().expect("Invalid address format");
|
||||
|
||||
@@ -43,8 +43,7 @@ impl SessionManager {
|
||||
pub(crate) fn spawn_session(
|
||||
&self,
|
||||
remote_address: String,
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))] // Путь обязателен для мобилок
|
||||
tun_fd: Option<i32>,
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))] tun_fd: Option<i32>,
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))] cache_dir: String,
|
||||
) -> Arc<Session> {
|
||||
let runtime = get_runtime();
|
||||
@@ -62,11 +61,11 @@ impl SessionManager {
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
{
|
||||
cache_dir
|
||||
} // Используем путь из мобильного приложения
|
||||
}
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
{
|
||||
".".to_string()
|
||||
} // На ПК пишем в локальную папку
|
||||
}
|
||||
};
|
||||
|
||||
let mut dns_handler = DnsHandler::new(&cache_path);
|
||||
@@ -132,9 +131,9 @@ impl SessionManager {
|
||||
info!("Engine async task started");
|
||||
|
||||
tokio::select! {
|
||||
// Добавляем обработку результата прямо здесь
|
||||
|
||||
res = engine.run(tun_device) => {
|
||||
// Теперь эта ветка возвращает (), так как мы обработали результат
|
||||
|
||||
info!("Engine loop finished: {:?}", res);
|
||||
},
|
||||
_ = cancel_token_for_engine.cancelled() => {
|
||||
|
||||
@@ -114,22 +114,18 @@ impl ConnectionManager {
|
||||
fn handle_tcp(&mut self, handle: SocketHandle, socket: &mut tcp::Socket) {
|
||||
use tcp::State;
|
||||
|
||||
// 1. Очистка закрытых сокетов
|
||||
if socket.state() == State::Closed {
|
||||
// Если сокет закрыт, удаляем его сессию и помечаем на удаление из сета
|
||||
if self.active_tcp_sessions.contains_key(&handle) {
|
||||
debug!(%handle, "TCP session closed, removing from active sessions");
|
||||
self.active_tcp_sessions.remove(&handle);
|
||||
}
|
||||
|
||||
// Добавляем в очередь на удаление из SocketSet (чтобы освободить память)
|
||||
if !self.sockets_to_remove.contains(&handle) {
|
||||
self.sockets_to_remove.push(handle);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Инициализация сессии при установке соединения
|
||||
if socket.state() == State::Established && !self.active_tcp_sessions.contains_key(&handle) {
|
||||
let target = self.resolve_target(socket);
|
||||
|
||||
@@ -145,12 +141,10 @@ impl ConnectionManager {
|
||||
self.active_tcp_sessions.insert(handle, conn);
|
||||
}
|
||||
|
||||
// 3. Тик активной сессии (проброс данных в прокси)
|
||||
if let Some(conn) = self.active_tcp_sessions.get_mut(&handle) {
|
||||
if !conn.tick(socket) {
|
||||
debug!(%handle, "Connection tick failed, aborting.");
|
||||
socket.abort();
|
||||
// Сессия удалится на следующем проходе, когда стейт станет Closed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,9 +184,9 @@ impl ConnectionManager {
|
||||
|
||||
fn create_dynamic_tcp_socket<'a>(port: u16) -> tcp::Socket<'a> {
|
||||
let buf_size = match port {
|
||||
443 | 80 => 256 * 1024, // 256 KB для веба
|
||||
22 | 53 | 123 => 16 * 1024, // 16 KB для мелких протоколов (SSH, DNS over TCP, NTP)
|
||||
_ => 64 * 1024, // Дефолт
|
||||
443 | 80 => 256 * 1024,
|
||||
22 | 53 | 123 => 16 * 1024,
|
||||
_ => 64 * 1024,
|
||||
};
|
||||
|
||||
let mut socket = tcp::Socket::new(
|
||||
@@ -200,7 +194,7 @@ impl ConnectionManager {
|
||||
tcp::SocketBuffer::new(vec![0; buf_size]),
|
||||
);
|
||||
|
||||
socket.set_nagle_enabled(false); // Для отзывчивости (особенно в играх типа Silent Hill, если через VPN)
|
||||
socket.set_nagle_enabled(false);
|
||||
socket.set_ack_delay(None);
|
||||
socket
|
||||
}
|
||||
@@ -216,12 +210,10 @@ impl ConnectionManager {
|
||||
return;
|
||||
};
|
||||
|
||||
// Ищем только SYN (начало соединения)
|
||||
if tcp_packet.syn() && !tcp_packet.ack() {
|
||||
let dst_port = tcp_packet.dst_port();
|
||||
let dst_addr = ip_packet.dst_addr();
|
||||
|
||||
// Проверяем, не создали ли мы уже такой сокет на предыдущем шаге
|
||||
if !self.has_active_session(socket_set, dst_addr.into(), dst_port) {
|
||||
debug!(target: "netrunner", "Dynamic TCP: Creating socket for {}:{}", dst_addr, dst_port);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ use smoltcp::{
|
||||
};
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
// --- TokenBuffer (без изменений, он у тебя отличный) ---
|
||||
const TOKEN_BUFFER_LIST_MAX_SIZE: usize = 64;
|
||||
static TOKEN_BUFFER_LIST: LazyLock<Mutex<Vec<BytesMut>>> = LazyLock::new(|| Mutex::new(Vec::new()));
|
||||
|
||||
@@ -61,11 +60,10 @@ impl DerefMut for TokenBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
// --- VirtTunDevice ---
|
||||
pub struct VirtTunDevice {
|
||||
capabilities: DeviceCapabilities,
|
||||
rx_queue: mpsc::UnboundedReceiver<TokenBuffer>, // smoltcp читает отсюда
|
||||
tx_queue: mpsc::UnboundedSender<TokenBuffer>, // smoltcp пишет сюда
|
||||
rx_queue: mpsc::UnboundedReceiver<TokenBuffer>,
|
||||
tx_queue: mpsc::UnboundedSender<TokenBuffer>,
|
||||
rx_avail: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
@@ -74,8 +72,8 @@ impl VirtTunDevice {
|
||||
capabilities: DeviceCapabilities,
|
||||
) -> (
|
||||
Self,
|
||||
mpsc::UnboundedSender<TokenBuffer>, // Канал, чтобы закидывать пакеты в smoltcp
|
||||
mpsc::UnboundedReceiver<TokenBuffer>, // Канал, чтобы забирать готовые пакеты из smoltcp
|
||||
mpsc::UnboundedSender<TokenBuffer>,
|
||||
mpsc::UnboundedReceiver<TokenBuffer>,
|
||||
Arc<AtomicBool>,
|
||||
) {
|
||||
let (to_smoltcp_tx, to_smoltcp_rx) = mpsc::unbounded_channel();
|
||||
|
||||
@@ -29,11 +29,7 @@ pub struct Engine {
|
||||
socket_set: SocketSet<'static>,
|
||||
manager: ConnectionManager,
|
||||
device: VirtTunDevice,
|
||||
|
||||
// Канал для инъекции пакетов в smoltcp
|
||||
to_smoltcp_tx: UnboundedSender<TokenBuffer>,
|
||||
|
||||
// Временное хранилище канала выхода из smoltcp (отдадим воркеру в run)
|
||||
from_smoltcp_rx: Option<UnboundedReceiver<TokenBuffer>>,
|
||||
|
||||
avail: Arc<AtomicBool>,
|
||||
@@ -47,7 +43,7 @@ impl Engine {
|
||||
dns_handler: DnsHandler,
|
||||
) -> Self {
|
||||
let now = Engine::current_time();
|
||||
// Смотри, как чисто мы получаем компоненты:
|
||||
|
||||
let (mut device, to_smoltcp_tx, from_smoltcp_rx, avail) = VirtTunDevice::new(caps);
|
||||
let interface = Interface::new(config, &mut device, now);
|
||||
|
||||
@@ -69,25 +65,19 @@ impl Engine {
|
||||
info!("Current routes: {:?}", self.interface.routes());
|
||||
let (writer, reader) = tun.split().expect("Failed to split TUN");
|
||||
|
||||
// 1. Создаем трубу для ВХОДЯЩЕГО трафика: TUN -> Engine
|
||||
let (tun_to_engine_tx, mut tun_to_engine_rx) = mpsc::unbounded_channel();
|
||||
Self::spawn_tun_reader(reader, tun_to_engine_tx, self.avail.clone());
|
||||
|
||||
// 2. Запускаем трубу ИСХОДЯЩЕГО трафика: smoltcp -> TUN
|
||||
let from_smoltcp_rx = self.from_smoltcp_rx.take().expect("Engine started twice");
|
||||
Self::spawn_tun_writer(writer, from_smoltcp_rx);
|
||||
|
||||
let mut last_log = StdInstant::now();
|
||||
|
||||
// 3. Главный цикл (ДИСПЕТЧЕР)
|
||||
loop {
|
||||
// Читаем всё, что прилетело из операционной системы
|
||||
while let Ok(token) = tun_to_engine_rx.try_recv() {
|
||||
// АНАЛИЗ: Создаем сокет, если это новый SYN
|
||||
self.manager
|
||||
.try_create_socket_from_packet(&token, &mut self.socket_set);
|
||||
|
||||
// ПЕРЕДАЧА: Закидываем пакет в виртуальную сетевую карту smoltcp
|
||||
if self.to_smoltcp_tx.send(token).is_ok() {
|
||||
self.device.mark_rx_available();
|
||||
}
|
||||
@@ -131,7 +121,6 @@ impl Engine {
|
||||
sleep(sleep_duration).await;
|
||||
}
|
||||
|
||||
// Воркер: Читает ОС -> Шлет в Engine
|
||||
fn spawn_tun_reader(
|
||||
mut reader: DeviceReader,
|
||||
to_engine: UnboundedSender<TokenBuffer>,
|
||||
@@ -173,7 +162,6 @@ impl Engine {
|
||||
});
|
||||
}
|
||||
|
||||
// Воркер: Читает smoltcp -> Шлет в ОС
|
||||
fn spawn_tun_writer(
|
||||
mut writer: DeviceWriter,
|
||||
mut from_smoltcp: UnboundedReceiver<TokenBuffer>,
|
||||
|
||||
@@ -46,7 +46,7 @@ fn get_default_gateway() -> Option<String> {
|
||||
.output()
|
||||
.ok()?;
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
// Простой парсинг: ищем строку с 0.0.0.0 и берем IP из колонки шлюза
|
||||
|
||||
stdout
|
||||
.lines()
|
||||
.find(|line| line.contains("0.0.0.0"))
|
||||
@@ -59,19 +59,15 @@ pub fn setup_platform_routing(remote_address: &str) -> io::Result<()> {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
// 1. Ядро
|
||||
let _ = run_cmd_ext("sysctl -w net.ipv4.conf.all.rp_filter=0", true);
|
||||
let _ = run_cmd_ext("sysctl -w net.ipv4.conf.netr0.rp_filter=0", true);
|
||||
let _ = run_cmd_ext("sysctl -w net.ipv4.ip_forward=1", true);
|
||||
|
||||
// 2. Маршрутизация
|
||||
let _ = run_cmd_ext("ip rule add fwmark 0x1 table 100", true);
|
||||
let _ = run_cmd_ext("ip route add default dev netr0 table 100", true);
|
||||
|
||||
// 3. NFTables (Чиним ошибку удаления и синтаксис)
|
||||
// Добавляем таблицу (если есть — ничего не сделает, если нет — создаст)
|
||||
run_cmd_ext("nft add table ip netrunner", true)?;
|
||||
// Очищаем таблицу перед работой, чтобы не плодить дубликаты
|
||||
|
||||
run_cmd_ext("nft flush table ip netrunner", true)?;
|
||||
|
||||
run_cmd_ext(
|
||||
@@ -95,7 +91,6 @@ pub fn setup_platform_routing(remote_address: &str) -> io::Result<()> {
|
||||
);
|
||||
run_cmd_ext(&dns_redir, false)?;
|
||||
|
||||
// 4. DNS (resolvectl не знает 'metric', используем стандартный синтаксис)
|
||||
let _ = run_cmd_ext("resolvectl dns netr0 10.0.0.2", true);
|
||||
let _ = run_cmd_ext("resolvectl domain netr0 ~.", true);
|
||||
|
||||
@@ -106,17 +101,14 @@ pub fn setup_platform_routing(remote_address: &str) -> io::Result<()> {
|
||||
{
|
||||
let gateway = get_default_gateway().unwrap_or_else(|| "192.168.1.1".to_string());
|
||||
|
||||
// 1. Устанавливаем IP для адаптера
|
||||
let _ = run_cmd_ext(
|
||||
"netsh interface ipv4 set address name=\"netr0\" static 10.0.0.1 255.255.255.0 none",
|
||||
true,
|
||||
);
|
||||
|
||||
// 2. Ждем и получаем индекс именно нашего туннеля
|
||||
let tun_idx = get_adapter_index("netr0")
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Interface netr0 not found"))?;
|
||||
|
||||
// 3. Маршрут-исключение для прокси через физический шлюз
|
||||
let _ = run_cmd_ext(
|
||||
&format!(
|
||||
"route add {} mask 255.255.255.255 {} metric 1",
|
||||
@@ -125,7 +117,6 @@ pub fn setup_platform_routing(remote_address: &str) -> io::Result<()> {
|
||||
true,
|
||||
);
|
||||
|
||||
// 4. Глобальные маршруты через TUN (теперь с правильным if_idx)
|
||||
run_cmd_ext(
|
||||
&format!(
|
||||
"route add 0.0.0.0 mask 128.0.0.0 10.0.0.2 if {} metric 5",
|
||||
@@ -141,7 +132,6 @@ pub fn setup_platform_routing(remote_address: &str) -> io::Result<()> {
|
||||
true,
|
||||
)?;
|
||||
|
||||
// 5. DNS
|
||||
let _ = run_cmd_ext(
|
||||
"netsh interface ipv4 set dnsservers name=\"netr0\" static 10.0.0.2 primary",
|
||||
true,
|
||||
@@ -172,7 +162,6 @@ pub fn reset_platform_routing(proxy_ip: Option<&str>) -> io::Result<()> {
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
// Очищаем глобальные маршруты, иначе интернет не вернется
|
||||
let _ = run_cmd_ext("route delete 0.0.0.0 mask 128.0.0.0", true);
|
||||
let _ = run_cmd_ext("route delete 128.0.0.0 mask 128.0.0.0", true);
|
||||
|
||||
@@ -180,7 +169,6 @@ pub fn reset_platform_routing(proxy_ip: Option<&str>) -> io::Result<()> {
|
||||
let _ = run_cmd_ext(&format!("route delete {}", ip), true);
|
||||
}
|
||||
|
||||
// Сбрасываем DNS на автоматический (или удаляем наш)
|
||||
let _ = run_cmd_ext(
|
||||
"netsh interface ipv4 set dnsservers name=\"netr0\" source=dhcp",
|
||||
true,
|
||||
|
||||
Reference in New Issue
Block a user