pre saved
This commit is contained in:
@@ -1,3 +0,0 @@
|
|||||||
struct TcpConnection {}
|
|
||||||
|
|
||||||
impl TcpConnection {}
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod tcp_connection;
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
use netrunner_common::protocol::codec::socks::SocksRequest;
|
||||||
|
use smoltcp::iface::SocketHandle;
|
||||||
|
use smoltcp::socket::tcp;
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
use tokio::net::TcpStream; // Твой код парсера
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
|
pub enum ConnectionState {
|
||||||
|
/// Сокет только что принял соединение (SYN-ACK завершен)
|
||||||
|
Established,
|
||||||
|
/// Мы в процессе SOCKS5 рукопожатия с локальным прокси
|
||||||
|
Handshaking,
|
||||||
|
/// Соединение готово к передаче данных (Bridge)
|
||||||
|
Active,
|
||||||
|
/// Ошибка или закрытие
|
||||||
|
Closed,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TcpConnection {
|
||||||
|
handle: SocketHandle,
|
||||||
|
state: ConnectionState,
|
||||||
|
tx: mpsc::UnboundedSender<Vec<u8>>,
|
||||||
|
rx: mpsc::UnboundedReceiver<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TcpConnection {
|
||||||
|
pub fn new(
|
||||||
|
handle: SocketHandle,
|
||||||
|
proxy_addr: String,
|
||||||
|
target_addr: std::net::SocketAddr,
|
||||||
|
) -> Self {
|
||||||
|
let (tx_to_proxy, mut rx_from_smol) = mpsc::unbounded_channel::<Vec<u8>>();
|
||||||
|
let (tx_to_smol, rx_from_proxy) = mpsc::unbounded_channel::<Vec<u8>>();
|
||||||
|
|
||||||
|
// Запускаем асинхронную логику в фоне
|
||||||
|
tokio::spawn(async move {
|
||||||
|
// 1. Подключаемся
|
||||||
|
let mut stream = match TcpStream::connect(&proxy_addr).await {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(_) => return, // Тут можно добавить логирование
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2. SOCKS Handshake
|
||||||
|
if SocksRequest::perform_client_handshake(&mut stream, &target_addr)
|
||||||
|
.await
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Читаем из прокси -> Пишем в канал для smoltcp
|
||||||
|
let from_proxy = async {
|
||||||
|
let mut buf = [0u8; 4096];
|
||||||
|
loop {
|
||||||
|
match reader.read(&mut buf).await {
|
||||||
|
Ok(0) | Err(_) => break,
|
||||||
|
Ok(n) => {
|
||||||
|
if tx_to_smol.send(buf[..n].to_vec()).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tokio::select! {
|
||||||
|
_ = to_proxy => {},
|
||||||
|
_ = from_proxy => {},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self {
|
||||||
|
handle,
|
||||||
|
state: ConnectionState::Active, // Сразу переходим в Active, т.к. задача пошла
|
||||||
|
tx: tx_to_proxy,
|
||||||
|
rx: rx_from_proxy,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll_and_process(&mut self, socket: &mut tcp::Socket) {
|
||||||
|
// 1. Из smoltcp -> В канал задачи
|
||||||
|
if socket.can_recv() {
|
||||||
|
let mut buf = [0u8; 4096];
|
||||||
|
if let Ok(n) = socket.recv_slice(&mut buf) {
|
||||||
|
if n > 0 {
|
||||||
|
let _ = self.tx.send(buf[..n].to_vec());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Из канала задачи -> В smoltcp
|
||||||
|
if socket.can_send() {
|
||||||
|
// try_recv не блокирует поток, что нам и нужно
|
||||||
|
if let Ok(data) = self.rx.try_recv() {
|
||||||
|
let _ = socket.send_slice(&data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
|
pub mod connections;
|
||||||
pub mod tun;
|
pub mod tun;
|
||||||
|
|||||||
+7
-5
@@ -13,12 +13,17 @@ async fn main() {
|
|||||||
info!("Initializing NetRunner Stack...");
|
info!("Initializing NetRunner Stack...");
|
||||||
let tun_device = Tun::create(|config| {
|
let tun_device = Tun::create(|config| {
|
||||||
config
|
config
|
||||||
|
.tun_name("tun0")
|
||||||
.address((10, 0, 0, 1))
|
.address((10, 0, 0, 1))
|
||||||
.netmask((255, 255, 255, 0))
|
.netmask((255, 255, 255, 0))
|
||||||
|
.destination((10, 0, 0, 2))
|
||||||
.up();
|
.up();
|
||||||
})
|
})
|
||||||
.expect("Failed to initialize TUN device");
|
.expect("Failed to initialize TUN device");
|
||||||
|
|
||||||
|
tun_device.clear_default_route();
|
||||||
|
tun_device.setup_linux_routes();
|
||||||
|
|
||||||
info!("TUN interface is UP: 10.0.0.1/24");
|
info!("TUN interface is UP: 10.0.0.1/24");
|
||||||
|
|
||||||
let config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
let config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
||||||
@@ -40,11 +45,8 @@ async fn main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let mut engine = Engine::new(config, caps, socks_addr);
|
let mut engine = Engine::new(config, caps, socks_addr);
|
||||||
|
engine.set_any_ip(true);
|
||||||
engine.add_address(smoltcp::wire::IpCidr::new(
|
engine.set_transparent_mode();
|
||||||
smoltcp::wire::IpAddress::v4(10, 0, 0, 2),
|
|
||||||
24,
|
|
||||||
));
|
|
||||||
|
|
||||||
info!("Stack IP initialized: 10.0.0.2");
|
info!("Stack IP initialized: 10.0.0.2");
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ use std::{
|
|||||||
};
|
};
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
use crate::tun::engine::START_TIME;
|
use crate::{connections::tcp_connection::TcpConnection, tun::engine::START_TIME};
|
||||||
pub struct ConnectionManager {
|
pub struct ConnectionManager {
|
||||||
last_activity: HashMap<SocketHandle, StdInstant>,
|
last_activity: HashMap<SocketHandle, StdInstant>,
|
||||||
|
active_tcp_sessions: HashMap<SocketHandle, TcpConnection>,
|
||||||
|
//active_udp_sessions: HashMap<SocketHandle, UdpSession>,
|
||||||
proxy_ip: String,
|
proxy_ip: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,6 +21,7 @@ impl ConnectionManager {
|
|||||||
pub fn new(ip: String) -> Self {
|
pub fn new(ip: String) -> Self {
|
||||||
Self {
|
Self {
|
||||||
last_activity: HashMap::new(),
|
last_activity: HashMap::new(),
|
||||||
|
active_tcp_sessions: HashMap::new(),
|
||||||
proxy_ip: ip,
|
proxy_ip: ip,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,31 +48,33 @@ impl ConnectionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_tcp(&mut self, handle: SocketHandle, socket: &mut tcp::Socket) {
|
fn handle_tcp(&mut self, handle: SocketHandle, socket: &mut tcp::Socket) {
|
||||||
// Важно: проверяем, есть ли что принимать
|
if socket.state() == tcp::State::Established {
|
||||||
if socket.can_recv() {
|
let proxy_ip = self.proxy_ip.clone(); // Берем из конфига менеджера
|
||||||
let mut data_processed = false;
|
|
||||||
|
|
||||||
// Используем recv_slice или проверяем длину в recv
|
let conn = self.active_tcp_sessions.entry(handle).or_insert_with(|| {
|
||||||
let result = socket.recv(|data| {
|
// 1. Получаем endpoint и безопасно распаковываем его
|
||||||
if !data.is_empty() {
|
let endpoint = socket
|
||||||
debug!(handle=%handle, len=data.len(), "TCP: received data");
|
.remote_endpoint()
|
||||||
data_processed = true;
|
.expect("TCP socket in Established state must have a remote endpoint");
|
||||||
(data.len(), ())
|
|
||||||
} else {
|
// 2. Конвертируем smoltcp::wire::IpAddress в std::net::IpAddr
|
||||||
(0, ())
|
let ip: std::net::IpAddr = match endpoint.addr {
|
||||||
}
|
smoltcp::wire::IpAddress::Ipv4(v4) => std::net::IpAddr::V4(v4.into()),
|
||||||
|
smoltcp::wire::IpAddress::Ipv6(v6) => std::net::IpAddr::V6(v6.into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. Собираем финальный SocketAddr
|
||||||
|
let target_addr = std::net::SocketAddr::new(ip, endpoint.port);
|
||||||
|
|
||||||
|
info!(handle=%handle, target=%target_addr, "Creating new TcpConnection bridge");
|
||||||
|
TcpConnection::new(handle, proxy_ip, target_addr)
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Err(e) = result {
|
conn.poll_and_process(socket);
|
||||||
debug!(handle=%handle, "TCP recv error: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if socket.state() == tcp::State::Closed {
|
||||||
// Если сокет закрывается, нужно дать ему закрыться, а не крутить вечно
|
self.active_tcp_sessions.remove(&handle);
|
||||||
if !socket.may_recv() && socket.state() == tcp::State::CloseWait {
|
|
||||||
socket.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,16 +131,43 @@ impl ConnectionManager {
|
|||||||
const TARGET_FREE_TCP: usize = 16;
|
const TARGET_FREE_TCP: usize = 16;
|
||||||
const TARGET_FREE_UDP: usize = 8;
|
const TARGET_FREE_UDP: usize = 8;
|
||||||
|
|
||||||
let tcp_listeners = socket_set
|
for &port in &[80, 443, 8080] {
|
||||||
.iter()
|
let current_port_sockets = socket_set
|
||||||
.filter(|(_, s)| {
|
.iter()
|
||||||
if let Some(tcp) = tcp::Socket::downcast(s) {
|
.filter(|(_, s)| {
|
||||||
tcp.state() == tcp::State::Listen
|
if let Some(tcp) = tcp::Socket::downcast(s) {
|
||||||
} else {
|
// Если эндпоинт есть - сверяем порт
|
||||||
false
|
if let Some(endpoint) = tcp.local_endpoint() {
|
||||||
|
return endpoint.port == port;
|
||||||
|
}
|
||||||
|
|
||||||
|
// КЛЮЧЕВОЙ МОМЕНТ:
|
||||||
|
// Если эндпоинта НЕТ, но сокет НЕ в состоянии CLOSED,
|
||||||
|
// или он только что был создан для прослушивания.
|
||||||
|
// В smoltcp после listen() сокет переходит в LISTEN,
|
||||||
|
// но local_endpoint может появиться чуть позже.
|
||||||
|
tcp.state() == tcp::State::Listen
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.count();
|
||||||
|
|
||||||
|
if current_port_sockets < 5 {
|
||||||
|
let mut s = Self::create_tcp_socket();
|
||||||
|
let endpoint = IpListenEndpoint { addr: None, port };
|
||||||
|
|
||||||
|
// Попробуй сначала listen, а потом добавлять
|
||||||
|
if s.listen(endpoint).is_ok() {
|
||||||
|
socket_set.add(s);
|
||||||
|
info!(
|
||||||
|
"--- REAL ADD --- Port: {}, Sockets for this port: {}",
|
||||||
|
port,
|
||||||
|
current_port_sockets + 1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.count();
|
}
|
||||||
|
|
||||||
let udp_active = socket_set
|
let udp_active = socket_set
|
||||||
.iter()
|
.iter()
|
||||||
@@ -146,20 +178,6 @@ impl ConnectionManager {
|
|||||||
.iter()
|
.iter()
|
||||||
.any(|(_, s)| icmp::Socket::downcast(s).is_some());
|
.any(|(_, s)| icmp::Socket::downcast(s).is_some());
|
||||||
|
|
||||||
if tcp_listeners < TARGET_FREE_TCP {
|
|
||||||
let diff = TARGET_FREE_TCP - tcp_listeners;
|
|
||||||
debug!("Refilling TCP pool: adding {} listeners", diff);
|
|
||||||
for _ in 0..diff {
|
|
||||||
let mut s = Self::create_tcp_socket();
|
|
||||||
let endpoint = IpListenEndpoint {
|
|
||||||
addr: None,
|
|
||||||
port: 8080,
|
|
||||||
};
|
|
||||||
s.listen(endpoint).unwrap();
|
|
||||||
socket_set.add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if udp_active < TARGET_FREE_UDP {
|
if udp_active < TARGET_FREE_UDP {
|
||||||
let diff = TARGET_FREE_UDP - udp_active;
|
let diff = TARGET_FREE_UDP - udp_active;
|
||||||
debug!("Refilling UDP pool: adding {} sockets", diff);
|
debug!("Refilling UDP pool: adding {} sockets", diff);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use smoltcp::{
|
|||||||
iface::{Config, Interface, SocketSet},
|
iface::{Config, Interface, SocketSet},
|
||||||
phy::DeviceCapabilities,
|
phy::DeviceCapabilities,
|
||||||
};
|
};
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
use std::{
|
use std::{
|
||||||
mem,
|
mem,
|
||||||
sync::{Arc, LazyLock, atomic::AtomicBool},
|
sync::{Arc, LazyLock, atomic::AtomicBool},
|
||||||
@@ -13,7 +14,7 @@ use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
|||||||
use tokio::time::{Duration, sleep};
|
use tokio::time::{Duration, sleep};
|
||||||
use tun::{DeviceReader, DeviceWriter};
|
use tun::{DeviceReader, DeviceWriter};
|
||||||
|
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use crate::tun::connection_manager::ConnectionManager;
|
use crate::tun::connection_manager::ConnectionManager;
|
||||||
use crate::tun::device::{TokenBuffer, VirtTunDevice};
|
use crate::tun::device::{TokenBuffer, VirtTunDevice};
|
||||||
@@ -34,7 +35,8 @@ impl Engine {
|
|||||||
pub fn new(config: Config, caps: DeviceCapabilities, ip: String) -> Self {
|
pub fn new(config: Config, caps: DeviceCapabilities, ip: String) -> Self {
|
||||||
let now = Engine::current_time();
|
let now = Engine::current_time();
|
||||||
let (mut device, bridge_rx, bridge_tx, avail) = VirtTunDevice::new(caps);
|
let (mut device, bridge_rx, bridge_tx, avail) = VirtTunDevice::new(caps);
|
||||||
let interface = Interface::new(config, &mut device, now);
|
let mut interface = Interface::new(config, &mut device, now);
|
||||||
|
|
||||||
let socket_set = SocketSet::new(vec![]);
|
let socket_set = SocketSet::new(vec![]);
|
||||||
Self {
|
Self {
|
||||||
interface,
|
interface,
|
||||||
@@ -141,4 +143,39 @@ impl Engine {
|
|||||||
.add_default_ipv4_route(smoltcp::wire::Ipv4Address::new(10, 0, 0, 1))
|
.add_default_ipv4_route(smoltcp::wire::Ipv4Address::new(10, 0, 0, 1))
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_any_ip(&mut self, state: bool) -> () {
|
||||||
|
self.interface.set_any_ip(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_transparent_mode(&mut self) {
|
||||||
|
info!("Switching engine to transparent mode (AnyIP + 0.0.0.0/0)");
|
||||||
|
|
||||||
|
self.interface.set_any_ip(true);
|
||||||
|
self.interface.update_ip_addrs(|addrs| {
|
||||||
|
addrs.clear();
|
||||||
|
addrs
|
||||||
|
.push(smoltcp::wire::IpCidr::new(
|
||||||
|
smoltcp::wire::IpAddress::v4(0, 0, 0, 0),
|
||||||
|
0,
|
||||||
|
))
|
||||||
|
.expect("Failed to set 0.0.0.0/0");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Устанавливаем дефолтный маршрут "в никуда" (локально)
|
||||||
|
self.interface.routes_mut().remove_default_ipv4_route();
|
||||||
|
self.interface
|
||||||
|
.routes_mut()
|
||||||
|
.add_default_ipv4_route(smoltcp::wire::Ipv4Address::new(0, 0, 0, 0))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_default_gateway(&mut self, gateway: smoltcp::wire::Ipv4Address) {
|
||||||
|
info!("Setting default IPv4 gateway to: {}", gateway);
|
||||||
|
self.interface.routes_mut().remove_default_ipv4_route();
|
||||||
|
self.interface
|
||||||
|
.routes_mut()
|
||||||
|
.add_default_ipv4_route(gateway)
|
||||||
|
.expect("Failed to set default gateway");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-1
@@ -1,5 +1,5 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use tracing::error;
|
use tracing::{error, info, warn};
|
||||||
use tun::{AsyncDevice, Configuration, DeviceReader, DeviceWriter, create_as_async};
|
use tun::{AsyncDevice, Configuration, DeviceReader, DeviceWriter, create_as_async};
|
||||||
|
|
||||||
pub struct Tun {
|
pub struct Tun {
|
||||||
@@ -42,4 +42,38 @@ impl Tun {
|
|||||||
let (writer, reader) = self.device.split()?;
|
let (writer, reader) = self.device.split()?;
|
||||||
Ok((writer, reader))
|
Ok((writer, reader))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setup_linux_routes(&self) -> io::Result<()> {
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
// Направляем трафик через IP, который слушает твой smoltcp Engine
|
||||||
|
// Предположим, smoltcp настроен на 10.0.0.2
|
||||||
|
let status = Command::new("ip")
|
||||||
|
.args(&["route", "add", "default", "via", "10.0.0.2", "dev", "tun0"])
|
||||||
|
.status()?;
|
||||||
|
|
||||||
|
if !status.success() {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"Failed to setup routes",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_default_route(&self) -> io::Result<()> {
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
info!("Removing existing default route...");
|
||||||
|
|
||||||
|
// Удаляем текущий маршрут по умолчанию
|
||||||
|
let status = Command::new("sudo")
|
||||||
|
.args(&["ip", "route", "del", "default"])
|
||||||
|
.status()?;
|
||||||
|
|
||||||
|
if !status.success() {
|
||||||
|
warn!("Could not delete default route (maybe it doesn't exist?)");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,9 +162,17 @@ pub enum SocksReply {
|
|||||||
port: u16,
|
port: u16,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TargetAddress {
|
||||||
|
Ipv4(std::net::Ipv4Addr),
|
||||||
|
Domain(String),
|
||||||
|
Ipv6(std::net::Ipv6Addr),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SocksTarget {
|
pub struct SocksTarget {
|
||||||
pub host: Bytes,
|
pub addr: TargetAddress,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,18 +202,22 @@ impl SocksReply {
|
|||||||
|
|
||||||
impl SocksTarget {
|
impl SocksTarget {
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
if self.host.len() == 4 {
|
match &self.addr {
|
||||||
// Похоже на IPv4
|
// Если это IPv4, у нас уже есть объект Ipv4Addr
|
||||||
let ip =
|
TargetAddress::Ipv4(ip) => {
|
||||||
std::net::Ipv4Addr::new(self.host[0], self.host[1], self.host[2], self.host[3]);
|
format!("{}:{}", ip, self.port)
|
||||||
format!("{}:{}", ip, self.port)
|
}
|
||||||
} else if self.host.len() == 16 {
|
|
||||||
// Похоже на IPv6
|
// Если это IPv6, объект Ipv6Addr (автоматически добавит скобки при надобности или используй формат)
|
||||||
format!("[...]:{}", self.port)
|
TargetAddress::Ipv6(ip) => {
|
||||||
} else {
|
format!("[{}]:{}", ip, self.port)
|
||||||
// Считаем, что это домен (текст)
|
}
|
||||||
let host_str = String::from_utf8_lossy(&self.host);
|
|
||||||
format!("{}:{}", host_str, self.port)
|
// Если это домен, то это String. Вычищаем нули на всякий случай
|
||||||
|
TargetAddress::Domain(domain) => {
|
||||||
|
let clean_domain = domain.replace('\0', "");
|
||||||
|
format!("{}:{}", clean_domain, self.port)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,18 +43,27 @@ impl Parser for SocksTarget {
|
|||||||
let mut packet = bytes.split_to(total_len);
|
let mut packet = bytes.split_to(total_len);
|
||||||
packet.advance(SOCKS5_MIN_HEADER);
|
packet.advance(SOCKS5_MIN_HEADER);
|
||||||
|
|
||||||
let host = if atyp == ATYP_DOMAIN {
|
let addr = match atyp {
|
||||||
let len = packet.get_u8() as usize;
|
ATYP_IPV4 => {
|
||||||
packet.split_to(len).freeze()
|
let octets: [u8; 4] = packet.split_to(4)[..].try_into().unwrap();
|
||||||
} else if atyp == ATYP_IPV4 {
|
TargetAddress::Ipv4(octets.into())
|
||||||
packet.split_to(IPV4_SIZE).freeze()
|
}
|
||||||
} else {
|
ATYP_DOMAIN => {
|
||||||
packet.split_to(IPV6_SIZE).freeze()
|
let len = packet.get_u8() as usize;
|
||||||
|
let domain_bytes = packet.split_to(len);
|
||||||
|
let domain = String::from_utf8(domain_bytes.to_vec())
|
||||||
|
.map_err(|_| "Invalid UTF-8 domain".to_string())?;
|
||||||
|
TargetAddress::Domain(domain)
|
||||||
|
}
|
||||||
|
ATYP_IPV6 => {
|
||||||
|
let octets: [u8; 16] = packet.split_to(16)[..].try_into().unwrap();
|
||||||
|
TargetAddress::Ipv6(octets.into())
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let port = packet.get_u16();
|
let port = packet.get_u16();
|
||||||
|
Ok(Some(SocksTarget { addr, port }))
|
||||||
Ok(Some(SocksTarget { host, port }))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,9 +143,7 @@ impl Connection {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let stream_id = muxer.next_id();
|
let stream_id = muxer.next_id();
|
||||||
let target_str = match &target {
|
let target_str = target.to_string();
|
||||||
SocksTarget { host, port } => format!("{}:{}", String::from_utf8_lossy(host), port),
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- НОВАЯ ЛОГИКА ОЖИДАНИЯ ---
|
// --- НОВАЯ ЛОГИКА ОЖИДАНИЯ ---
|
||||||
// Регистрируем временный канал, чтобы получить Connect-подтверждение от сервера
|
// Регистрируем временный канал, чтобы получить Connect-подтверждение от сервера
|
||||||
|
|||||||
Reference in New Issue
Block a user