From 5e99c9f87405b99bfd558445dc6768d5edb6afd5 Mon Sep 17 00:00:00 2001 From: "Remy D. Farley" Date: Wed, 3 Apr 2024 14:20:05 +0000 Subject: [PATCH] add no-proxy mode --- src/args.rs | 10 +++++ src/lib.rs | 3 ++ src/no_proxy.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 src/no_proxy.rs diff --git a/src/args.rs b/src/args.rs index 309f7d0..e7df38c 100644 --- a/src/args.rs +++ b/src/args.rs @@ -249,6 +249,14 @@ impl std::fmt::Display for ArgProxy { impl ArgProxy { pub fn from_url(s: &str) -> Result { + if s == "none" { + return Ok(ArgProxy { + proxy_type: ProxyType::None, + addr: "0.0.0.0:0".parse().unwrap(), + credentials: None, + }); + } + let e = format!("`{s}` is not a valid proxy URL"); let url = url::Url::parse(s).map_err(|_| Error::from(&e))?; let e = format!("`{s}` does not contain a host"); @@ -299,6 +307,7 @@ pub enum ProxyType { Socks4, #[default] Socks5, + None, } impl std::fmt::Display for ProxyType { @@ -307,6 +316,7 @@ impl std::fmt::Display for ProxyType { ProxyType::Socks4 => write!(f, "socks4"), ProxyType::Socks5 => write!(f, "socks5"), ProxyType::Http => write!(f, "http"), + ProxyType::None => write!(f, "none"), } } } diff --git a/src/lib.rs b/src/lib.rs index 6a8f699..e2701fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use crate::{ directions::{IncomingDataEvent, IncomingDirection, OutgoingDirection}, http::HttpManager, + no_proxy::NoProxyManager, session_info::{IpProtocol, SessionInfo}, virtual_dns::VirtualDns, }; @@ -42,6 +43,7 @@ mod dump_logger; mod error; mod http; mod mobile_api; +mod no_proxy; mod proxy_handler; mod session_info; mod socks; @@ -81,6 +83,7 @@ where ProxyType::Socks5 => Arc::new(SocksProxyManager::new(server_addr, V5, key)) as Arc, ProxyType::Socks4 => Arc::new(SocksProxyManager::new(server_addr, V4, key)) as Arc, ProxyType::Http => Arc::new(HttpManager::new(server_addr, key)) as Arc, + ProxyType::None => Arc::new(NoProxyManager::new(server_addr)) as Arc, }; let mut ipstack_config = ipstack::IpStackConfig::default(); diff --git a/src/no_proxy.rs b/src/no_proxy.rs new file mode 100644 index 0000000..99c4dbf --- /dev/null +++ b/src/no_proxy.rs @@ -0,0 +1,109 @@ +use crate::{ + directions::{IncomingDataEvent, IncomingDirection, OutgoingDataEvent, OutgoingDirection}, + proxy_handler::{ProxyHandler, ProxyHandlerManager}, + session_info::SessionInfo, +}; +use std::{collections::VecDeque, net::SocketAddr, sync::Arc}; +use tokio::sync::Mutex; + +struct NoProxyHandler { + info: SessionInfo, + domain_name: Option, + client_outbuf: VecDeque, + server_outbuf: VecDeque, + udp_associate: bool, +} + +#[async_trait::async_trait] +impl ProxyHandler for NoProxyHandler { + fn get_session_info(&self) -> SessionInfo { + self.info + } + + fn get_domain_name(&self) -> Option { + self.domain_name.clone() + } + + async fn push_data(&mut self, event: IncomingDataEvent<'_>) -> std::io::Result<()> { + let IncomingDataEvent { direction, buffer } = event; + match direction { + IncomingDirection::FromServer => { + self.client_outbuf.extend(buffer.iter()); + } + IncomingDirection::FromClient => { + self.server_outbuf.extend(buffer.iter()); + } + } + Ok(()) + } + + fn consume_data(&mut self, dir: OutgoingDirection, size: usize) { + let buffer = match dir { + OutgoingDirection::ToServer => &mut self.server_outbuf, + OutgoingDirection::ToClient => &mut self.client_outbuf, + }; + buffer.drain(0..size); + } + + fn peek_data(&mut self, dir: OutgoingDirection) -> OutgoingDataEvent { + let buffer = match dir { + OutgoingDirection::ToServer => &mut self.server_outbuf, + OutgoingDirection::ToClient => &mut self.client_outbuf, + }; + OutgoingDataEvent { + direction: dir, + buffer: buffer.make_contiguous(), + } + } + + fn connection_established(&self) -> bool { + true + } + + fn data_len(&self, dir: OutgoingDirection) -> usize { + match dir { + OutgoingDirection::ToServer => self.server_outbuf.len(), + OutgoingDirection::ToClient => self.client_outbuf.len(), + } + } + + fn reset_connection(&self) -> bool { + false + } + + fn get_udp_associate(&self) -> Option { + self.udp_associate.then_some(self.info.dst) + } +} + +pub(crate) struct NoProxyManager { + server: SocketAddr, +} + +#[async_trait::async_trait] +impl ProxyHandlerManager for NoProxyManager { + async fn new_proxy_handler( + &self, + info: SessionInfo, + domain_name: Option, + udp_associate: bool, + ) -> std::io::Result>> { + Ok(Arc::new(Mutex::new(NoProxyHandler { + info, + domain_name, + client_outbuf: VecDeque::default(), + server_outbuf: VecDeque::default(), + udp_associate, + }))) + } + + fn get_server_addr(&self) -> SocketAddr { + self.server + } +} + +impl NoProxyManager { + pub(crate) fn new(server: SocketAddr) -> Self { + Self { server } + } +}