clean project from comments
This commit is contained in:
@@ -4,17 +4,13 @@ use hickory_proto::rr::{RData, Record};
|
||||
use crate::connections::ip_store::FakeIpStore;
|
||||
|
||||
pub fn handle_dns_query(data: &[u8], store: &mut FakeIpStore) -> Option<Vec<u8>> {
|
||||
// 1. Парсим входящий запрос
|
||||
let request = Message::from_vec(data).ok()?;
|
||||
|
||||
// 2. Берем первый вопрос (обычно запрос только один)
|
||||
let query = request.queries().first()?;
|
||||
let name = query.name().to_string().trim_end_matches('.').to_string();
|
||||
|
||||
// 3. Получаем Fake IP
|
||||
let fake_ip = store.get_or_assign(&name);
|
||||
|
||||
// 4. Формируем ответ
|
||||
let mut response = Message::new();
|
||||
response
|
||||
.set_recursion_available(true)
|
||||
@@ -23,14 +19,8 @@ pub fn handle_dns_query(data: &[u8], store: &mut FakeIpStore) -> Option<Vec<u8>>
|
||||
.set_response_code(ResponseCode::NoError)
|
||||
.add_query(query.clone());
|
||||
|
||||
// Создаем запись A (IPv4)
|
||||
let record = Record::from_rdata(
|
||||
query.name().clone(),
|
||||
1, // TTL = 1 сек
|
||||
RData::A(fake_ip.into()),
|
||||
);
|
||||
let record = Record::from_rdata(query.name().clone(), 1, RData::A(fake_ip.into()));
|
||||
response.add_answer(record);
|
||||
|
||||
// 5. Сериализуем обратно в байты
|
||||
response.to_vec().ok()
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ pub struct FakeIpStore {
|
||||
next_ip: u32,
|
||||
}
|
||||
|
||||
const START_IP: u32 = 0x64400001; // 100.64.0.1 (IP for Service Networks/Shared Address Space)
|
||||
const START_IP: u32 = 0x64400001;
|
||||
|
||||
impl FakeIpStore {
|
||||
pub fn new() -> Self {
|
||||
|
||||
@@ -2,7 +2,7 @@ use netrunner_core::protocol::codec::socks::{SocksRequest, TargetAddress};
|
||||
use smoltcp::iface::SocketHandle;
|
||||
use smoltcp::socket::tcp;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpStream; // Твой код парсера
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::{mpsc, oneshot};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::{debug, info, trace, warn};
|
||||
@@ -44,10 +44,9 @@ impl TcpConnection {
|
||||
Err(e) => {
|
||||
debug!(%handle, error = %e, "Failed to connect to proxy");
|
||||
return;
|
||||
} // Тут можно добавить логирование
|
||||
}
|
||||
};
|
||||
|
||||
// 2. SOCKS Handshake
|
||||
if let Err(e) = SocksRequest::perform_client_handshake(&mut stream, &target_addr).await
|
||||
{
|
||||
debug!(%handle, error = %e, "SOCKS handshake failed");
|
||||
@@ -58,10 +57,8 @@ impl TcpConnection {
|
||||
|
||||
debug!(%handle, "SOCKS handshake successful, starting data bridge");
|
||||
|
||||
// 3. Копирование данных (Bridge)
|
||||
let (mut reader, mut writer) = stream.into_split();
|
||||
|
||||
// Читаем из канала -> Пишем в прокси
|
||||
let to_proxy = async {
|
||||
while let Some(data) = rx_from_smol.recv().await {
|
||||
if writer.write_all(&data).await.is_err() {
|
||||
@@ -70,7 +67,6 @@ impl TcpConnection {
|
||||
}
|
||||
};
|
||||
|
||||
// Читаем из прокси -> Пишем в канал для smoltcp
|
||||
let from_proxy = async {
|
||||
let mut buf = [0u8; 65536];
|
||||
loop {
|
||||
@@ -94,7 +90,7 @@ impl TcpConnection {
|
||||
|
||||
Self {
|
||||
handle,
|
||||
state: ConnectionState::Active, // Сразу переходим в Active, т.к. задача пошла
|
||||
state: ConnectionState::Active,
|
||||
tx: tx_to_proxy,
|
||||
rx: rx_from_proxy,
|
||||
pending_data: vec![],
|
||||
@@ -105,7 +101,6 @@ impl TcpConnection {
|
||||
|
||||
pub fn tick(&mut self, socket: &mut tcp::Socket) -> bool {
|
||||
let state = socket.state();
|
||||
//trace!(handle=%self.handle, ?state, "Tick");
|
||||
|
||||
match self.state {
|
||||
ConnectionState::Handshaking => {
|
||||
@@ -114,23 +109,22 @@ impl TcpConnection {
|
||||
Ok(_) => {
|
||||
self.state = ConnectionState::Active;
|
||||
self.handshake_rx = None;
|
||||
return true; // Успех
|
||||
return true;
|
||||
}
|
||||
Err(oneshot::error::TryRecvError::Empty) => return true, // Ждем
|
||||
Err(oneshot::error::TryRecvError::Empty) => return true,
|
||||
Err(oneshot::error::TryRecvError::Closed) => {
|
||||
self.state = ConnectionState::Closed; // ФЕЙЛ
|
||||
return false; // СКАЗАТЬ МЕНЕДЖЕРУ УДАЛИТЬ НАС
|
||||
self.state = ConnectionState::Closed;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false; // Если rx пропал, но мы не Active — закрываем
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionState::Active => {
|
||||
self.poll_and_process(socket);
|
||||
|
||||
// FIN от удалённой стороны
|
||||
if state == tcp::State::CloseWait {
|
||||
socket.close();
|
||||
self.state = ConnectionState::Closed;
|
||||
@@ -164,7 +158,6 @@ impl TcpConnection {
|
||||
}
|
||||
|
||||
fn poll_and_process(&mut self, socket: &mut tcp::Socket) {
|
||||
// 1. сначала читаем smoltcp
|
||||
if socket.can_recv() {
|
||||
let _ = socket.recv(|data| {
|
||||
let len = data.len();
|
||||
@@ -175,12 +168,11 @@ impl TcpConnection {
|
||||
});
|
||||
}
|
||||
|
||||
// 2. потом отправляем proxy → smoltcp
|
||||
if !self.pending_data.is_empty() {
|
||||
if self.pending_data.len() > MAX_PENDING {
|
||||
warn!(%self.handle, "Buffer overflow! Aborting connection.");
|
||||
socket.abort(); // Убиваем сокет
|
||||
self.token.cancel(); // Говорим tokio-задаче умереть
|
||||
socket.abort();
|
||||
self.token.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -188,7 +180,7 @@ impl TcpConnection {
|
||||
Ok(n) => {
|
||||
self.pending_data.drain(0..n);
|
||||
}
|
||||
Err(_) => {} // Оставляем в pending_data на следующий тик
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-10
@@ -45,7 +45,6 @@ impl Session {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Фабрика (SessionManager) ---
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct SessionManager;
|
||||
|
||||
@@ -70,18 +69,13 @@ impl SessionManager {
|
||||
} else {
|
||||
info!("Creating TUN device manually");
|
||||
Tun::create(|config| {
|
||||
config
|
||||
.tun_name("tun0")
|
||||
.address((10, 0, 0, 1))
|
||||
// ... настройки ...
|
||||
.up();
|
||||
config.tun_name("tun0").address((10, 0, 0, 1)).up();
|
||||
})
|
||||
.expect("Failed to init TUN")
|
||||
};
|
||||
|
||||
setup_platform_routing(&tun_device, &remote_address);
|
||||
|
||||
// 2. Инициализация сети
|
||||
let config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
||||
let mut caps = DeviceCapabilities::default();
|
||||
caps.max_transmission_unit = 1500;
|
||||
@@ -97,13 +91,13 @@ impl SessionManager {
|
||||
|
||||
let proxy_ip = network.get_self_local_address();
|
||||
info!("Proxy self address: {:?}", proxy_ip);
|
||||
// Запускаем сетевой поток
|
||||
|
||||
let net_handle = tokio::spawn(async move {
|
||||
network.run().await;
|
||||
});
|
||||
|
||||
info!("Configuring Engine...");
|
||||
// 3. Инициализация Engine
|
||||
|
||||
let mut engine = Engine::new(config, caps, proxy_ip);
|
||||
engine.set_any_ip(true);
|
||||
engine.set_transparent_mode();
|
||||
@@ -112,7 +106,6 @@ impl SessionManager {
|
||||
|
||||
info!("Engine activated");
|
||||
|
||||
// 4. Главный цикл с поддержкой остановки
|
||||
tokio::select! {
|
||||
res = engine.run(tun_device) => {
|
||||
error!("Engine loop terminated unexpectedly: {:?}", res);
|
||||
|
||||
+1
-5
@@ -13,7 +13,6 @@ use tracing::{error, info};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// 1. Инициализируем систему логирования
|
||||
logger_init();
|
||||
info!("Initializing NetRunner Stack...");
|
||||
let tun_device = Tun::create(|config| {
|
||||
@@ -46,8 +45,6 @@ async fn main() {
|
||||
|
||||
let proxy_ip = network.get_self_local_address();
|
||||
|
||||
// 2. ВЫНОСИМ СЕТЬ В ОТДЕЛЬНЫЙ ЦИКЛ
|
||||
// Это запустит SOCKS5 сервер и TLS туннель параллельно движку
|
||||
tokio::spawn(async move {
|
||||
info!("Network thread started");
|
||||
network.run().await;
|
||||
@@ -56,11 +53,10 @@ async fn main() {
|
||||
let mut engine = Engine::new(config, caps, proxy_ip);
|
||||
engine.set_any_ip(true);
|
||||
engine.set_transparent_mode();
|
||||
engine.set_default_gateway(Ipv4Addr::new(10, 0, 0, 2)); // to smoltcp
|
||||
engine.set_default_gateway(Ipv4Addr::new(10, 0, 0, 2));
|
||||
engine.activate();
|
||||
info!("Stack IP initialized: 10.0.0.2");
|
||||
|
||||
// 5. Запуск
|
||||
info!("Engine starting process loop...");
|
||||
engine.run(tun_device).await;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::tun::tun::Tun; // Убедись, что путь к Tun верный
|
||||
use crate::tun::tun::Tun;
|
||||
use std::io;
|
||||
|
||||
pub fn setup_platform_routing(tun_device: &Tun, remote_address: &str) -> io::Result<()> {
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::{
|
||||
pub struct ConnectionManager {
|
||||
last_activity: HashMap<SocketHandle, StdInstant>,
|
||||
active_tcp_sessions: HashMap<SocketHandle, TcpConnection>,
|
||||
//active_udp_sessions: HashMap<SocketHandle, UdpSession>,
|
||||
|
||||
fake_ip_store: FakeIpStore,
|
||||
proxy_ip: String,
|
||||
failed_until: HashMap<SocketHandle, StdInstant>,
|
||||
@@ -37,7 +37,6 @@ impl ConnectionManager {
|
||||
}
|
||||
pub fn start_listening(&mut self, socket_set: &mut SocketSet) {
|
||||
for (_, socket) in socket_set.iter_mut() {
|
||||
// Обработка TCP (как было)
|
||||
if let Some(tcp) = tcp::Socket::downcast_mut(socket) {
|
||||
if !tcp.is_open() {
|
||||
let endpoint = IpListenEndpoint {
|
||||
@@ -46,11 +45,8 @@ impl ConnectionManager {
|
||||
};
|
||||
let _ = tcp.listen(endpoint);
|
||||
}
|
||||
}
|
||||
// Добавляем обработку UDP
|
||||
else if let Some(udp) = udp::Socket::downcast_mut(socket) {
|
||||
} else if let Some(udp) = udp::Socket::downcast_mut(socket) {
|
||||
if !udp.is_open() {
|
||||
// Биндим на 53 порт, чтобы ловить DNS-запросы
|
||||
let endpoint = IpListenEndpoint {
|
||||
addr: None,
|
||||
port: 53,
|
||||
@@ -65,12 +61,11 @@ impl ConnectionManager {
|
||||
}
|
||||
|
||||
fn resolve_target(&self, socket: &tcp::Socket) -> TargetAddress {
|
||||
// Безопасно получаем эндпоинт
|
||||
let local_endpoint = match socket.local_endpoint() {
|
||||
Some(ep) => ep,
|
||||
None => {
|
||||
warn!(handle=?socket, "Attempted to resolve target for an unconnected socket");
|
||||
// Возвращаем дефолт, чтобы не падать
|
||||
|
||||
return TargetAddress::Domain("disconnected".to_string(), 0);
|
||||
}
|
||||
};
|
||||
@@ -116,11 +111,10 @@ impl ConnectionManager {
|
||||
fn handle_tcp(&mut self, handle: SocketHandle, socket: &mut tcp::Socket) {
|
||||
use tcp::State;
|
||||
|
||||
// 1. Если сокет закрыт, просто чистим и возвращаем в LISTEN
|
||||
if socket.state() == State::Closed {
|
||||
if let Some(until) = self.failed_until.get(&handle) {
|
||||
if StdInstant::now() < *until {
|
||||
return; // Сокет в штрафе, не открываем его
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,15 +124,11 @@ impl ConnectionManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Если сокет установлен, но в менеджере нет записи
|
||||
if socket.state() == State::Established && !self.active_tcp_sessions.contains_key(&handle) {
|
||||
let target = self.resolve_target(socket);
|
||||
|
||||
// ВАЖНО: Тут можно добавить проверку: если target "плохой" или не резолвится,
|
||||
// сразу убиваем сокет, чтобы не зацикливаться.
|
||||
if let TargetAddress::Domain(d, _) = &target {
|
||||
if d == "disconnected" {
|
||||
// Или другая логика проверки
|
||||
socket.abort();
|
||||
return;
|
||||
}
|
||||
@@ -148,13 +138,11 @@ 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) {
|
||||
// Если tick вернул false, значит сессия завершена или произошла ошибка в tokio-задаче
|
||||
debug!(%handle, "Connection handshake failed or closed, aborting socket.");
|
||||
self.active_tcp_sessions.remove(&handle);
|
||||
socket.abort(); // Принудительно закрываем "битый" сокет
|
||||
socket.abort();
|
||||
self.failed_until
|
||||
.insert(handle, StdInstant::now() + Duration::from_secs(5));
|
||||
}
|
||||
@@ -164,7 +152,6 @@ impl ConnectionManager {
|
||||
socket.abort();
|
||||
}
|
||||
|
||||
// 4. Обработка FIN
|
||||
if socket.state() == State::CloseWait {
|
||||
socket.close();
|
||||
}
|
||||
@@ -211,20 +198,16 @@ impl ConnectionManager {
|
||||
}
|
||||
|
||||
pub fn setup_sockets(n_tcp: usize, n_udp: usize, n_icmp: usize) -> SocketSet<'static> {
|
||||
// Создаем хранилище с запасом на все типы сокетов
|
||||
let mut sockets = SocketSet::new(Vec::with_capacity(n_tcp + n_udp + n_icmp));
|
||||
|
||||
// 1. Добавляем TCP сокеты
|
||||
for _ in 0..n_tcp {
|
||||
sockets.add(Self::create_tcp_socket());
|
||||
}
|
||||
|
||||
// 2. Добавляем UDP сокеты
|
||||
for _ in 0..n_udp {
|
||||
sockets.add(Self::create_udp_socket());
|
||||
}
|
||||
|
||||
// 3. Добавляем ICMP сокет
|
||||
for _ in 0..n_icmp {
|
||||
sockets.add(Self::create_icmp_socket());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
//! Virtual Device for receiving packets from tun
|
||||
|
||||
use std::{
|
||||
marker::PhantomData,
|
||||
mem,
|
||||
@@ -119,9 +117,6 @@ impl phy::TxToken for VirtTxToken<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
// Maximum number of TokenBuffer cached globally.
|
||||
//
|
||||
// Each of them has capacity 65536 (defined in tun/mod.rs), so 64 * 65536 = 4MB.
|
||||
const TOKEN_BUFFER_LIST_MAX_SIZE: usize = 64;
|
||||
static TOKEN_BUFFER_LIST: LazyLock<Mutex<Vec<BytesMut>>> = LazyLock::new(|| Mutex::new(Vec::new()));
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ impl Engine {
|
||||
pub fn set_transparent_mode(&mut self) {
|
||||
self.interface.update_ip_addrs(|addrs| {
|
||||
addrs.clear();
|
||||
//accept all internet
|
||||
|
||||
addrs
|
||||
.push(IpCidr::new(IpAddress::v4(10, 0, 0, 2), 24))
|
||||
.unwrap();
|
||||
|
||||
+2
-10
@@ -32,8 +32,8 @@ impl Tun {
|
||||
|
||||
pub fn from_android_fd(fd: i32) -> io::Result<Self> {
|
||||
let mut config = Configuration::default();
|
||||
config.raw_fd(fd); // Передаем дескриптор, который нам дал Android VpnService
|
||||
config.up(); // Убеждаемся, что он поднят
|
||||
config.raw_fd(fd);
|
||||
config.up();
|
||||
|
||||
Self::new(&config)
|
||||
}
|
||||
@@ -60,7 +60,6 @@ impl Tun {
|
||||
remote_address
|
||||
);
|
||||
|
||||
// 1. Находим текущий маршрут до прокси (до изменения default)
|
||||
let output = Command::new("ip")
|
||||
.args(&["route", "get", remote_address])
|
||||
.output()?;
|
||||
@@ -72,7 +71,6 @@ impl Tun {
|
||||
|
||||
info!("Обнаружен физический маршрут: dev={}, via={:?}", dev, via);
|
||||
|
||||
// 2. Добавляем статическое исключение для прокси
|
||||
info!("Добавляем статический маршрут для прокси...");
|
||||
let mut proxy_route = vec!["ip", "route", "add", remote_address, "dev", dev];
|
||||
if let Some(gw) = via {
|
||||
@@ -83,13 +81,11 @@ impl Tun {
|
||||
warn!("Маршрут к прокси уже существует или возникла ошибка (это нормально).");
|
||||
}
|
||||
|
||||
// 3. Удаляем старый default, если он есть
|
||||
info!("Переключаем default маршрут на tun0...");
|
||||
let _ = Command::new("sudo")
|
||||
.args(&["ip", "route", "del", "default"])
|
||||
.status();
|
||||
|
||||
// 4. Устанавливаем tun0 как основной default
|
||||
let status = Command::new("sudo")
|
||||
.args(&[
|
||||
"ip", "route", "add", "default", "via", "10.0.0.2", "dev", "tun0", "metric", "1",
|
||||
@@ -101,7 +97,6 @@ impl Tun {
|
||||
error!("Не удалось установить tun0 как default!");
|
||||
}
|
||||
|
||||
// 5. Добавляем резервный маршрут через физический интерфейс
|
||||
if let Some(gw) = via {
|
||||
info!("Добавляем резервный маршрут через {} с метрикой 100", dev);
|
||||
let _ = Command::new("sudo")
|
||||
@@ -116,11 +111,8 @@ impl Tun {
|
||||
}
|
||||
#[cfg(feature = "desktop")]
|
||||
pub fn setup_dns_redirection(&self) -> io::Result<()> {
|
||||
// 1. Создаем временный файл resolv.conf
|
||||
// Мы говорим системе: "Твой DNS-сервер теперь 10.0.0.1" (твой TUN-IP)
|
||||
let _ = std::fs::write("/tmp/resolv.conf.netrunner", "nameserver 10.0.0.2\n");
|
||||
|
||||
// 2. Применяем его (для Linux/systemd)
|
||||
let _ = std::process::Command::new("sudo")
|
||||
.args(&["cp", "/tmp/resolv.conf.netrunner", "/etc/resolv.conf"])
|
||||
.status();
|
||||
|
||||
Reference in New Issue
Block a user