From 1c68528fd16ad4274fd3dd2cd6df8e6a0a422b49 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 4 Sep 2024 11:01:37 +0800 Subject: [PATCH] Added simplesocks I'm adding this to debug/develop programs, don't use. --- leaf/Cargo.toml | 2 + leaf/src/app/inbound/manager.rs | 13 +++ leaf/src/config/conf/config.rs | 20 +++++ leaf/src/proxy/mod.rs | 2 + .../src/proxy/simplesocks/inbound/datagram.rs | 89 +++++++++++++++++++ leaf/src/proxy/simplesocks/inbound/mod.rs | 5 ++ leaf/src/proxy/simplesocks/inbound/stream.rs | 27 ++++++ leaf/src/proxy/simplesocks/mod.rs | 2 + 8 files changed, 160 insertions(+) create mode 100644 leaf/src/proxy/simplesocks/inbound/datagram.rs create mode 100644 leaf/src/proxy/simplesocks/inbound/mod.rs create mode 100644 leaf/src/proxy/simplesocks/inbound/stream.rs create mode 100644 leaf/src/proxy/simplesocks/mod.rs diff --git a/leaf/Cargo.toml b/leaf/Cargo.toml index 36d54ceb2..34332bcd3 100644 --- a/leaf/Cargo.toml +++ b/leaf/Cargo.toml @@ -60,6 +60,7 @@ all-endpoints = [ "inbound-http", "inbound-shadowsocks", "inbound-socks", + "inbound-simplesocks", "inbound-tun", "inbound-cat", # outbounds @@ -118,6 +119,7 @@ outbound-vmess = ["lz_fnv", "cfb-mode", "hmac", "aes", "sha3", "digest", "uuid", inbound-trojan = ["sha2", "hex"] inbound-shadowsocks = ["hkdf", "sha-1", "md-5", "tokio-util"] inbound-socks = [] +inbound-simplesocks = [] inbound-http = ["http"] inbound-tun = ["tun", "netstack-lwip", "pnet_datalink"] inbound-ws = ["tungstenite", "tokio-tungstenite", "url", "http"] diff --git a/leaf/src/app/inbound/manager.rs b/leaf/src/app/inbound/manager.rs index a8196249a..296522ec9 100644 --- a/leaf/src/app/inbound/manager.rs +++ b/leaf/src/app/inbound/manager.rs @@ -19,6 +19,8 @@ use crate::proxy::http; use crate::proxy::quic; #[cfg(feature = "inbound-shadowsocks")] use crate::proxy::shadowsocks; +#[cfg(feature = "inbound-simplesocks")] +use crate::proxy::simplesocks; #[cfg(feature = "inbound-socks")] use crate::proxy::socks; #[cfg(feature = "inbound-tls")] @@ -86,6 +88,17 @@ impl InboundManager { )); handlers.insert(tag.clone(), handler); } + #[cfg(feature = "inbound-simplesocks")] + "simplesocks" => { + let stream = Arc::new(simplesocks::inbound::StreamHandler); + let datagram = Arc::new(simplesocks::inbound::DatagramHandler); + let handler = Arc::new(proxy::inbound::Handler::new( + tag.clone(), + Some(stream), + Some(datagram), + )); + handlers.insert(tag.clone(), handler); + } #[cfg(feature = "inbound-http")] "http" => { let stream = Arc::new(http::inbound::StreamHandler); diff --git a/leaf/src/config/conf/config.rs b/leaf/src/config/conf/config.rs index a23c10168..bf1608f46 100644 --- a/leaf/src/config/conf/config.rs +++ b/leaf/src/config/conf/config.rs @@ -34,6 +34,8 @@ pub struct General { pub http_port: Option, pub socks_interface: Option, pub socks_port: Option, + pub simplesocks_interface: Option, + pub simplesocks_port: Option, pub api_interface: Option, pub api_port: Option, pub routing_domain_resolve: Option, @@ -331,6 +333,12 @@ pub fn from_lines(lines: Vec>) -> Result { "socks-port" => { general.socks_port = get_value::(parts[1]); } + "simplesocks-interface" => { + general.simplesocks_interface = get_string(parts[1]); + } + "simplesocks-port" => { + general.simplesocks_port = get_value::(parts[1]); + } "api-interface" => { general.api_interface = get_string(parts[1]); } @@ -775,6 +783,18 @@ pub fn to_internal(conf: &mut Config) -> Result { inbound.port = ext_general.socks_port.unwrap() as u32; inbounds.push(inbound); } + if ext_general.simplesocks_interface.is_some() && ext_general.simplesocks_port.is_some() { + let mut inbound = internal::Inbound::new(); + inbound.protocol = "simplesocks".to_string(); + inbound.tag = "simplesocks".to_string(); + inbound.address = ext_general + .simplesocks_interface + .as_ref() + .unwrap() + .to_string(); + inbound.port = ext_general.simplesocks_port.unwrap() as u32; + inbounds.push(inbound); + } if ext_general.tun_fd.is_some() || ext_general.tun_auto.is_some() diff --git a/leaf/src/proxy/mod.rs b/leaf/src/proxy/mod.rs index 4097ece47..ad341c2da 100644 --- a/leaf/src/proxy/mod.rs +++ b/leaf/src/proxy/mod.rs @@ -58,6 +58,8 @@ pub mod redirect; pub mod select; #[cfg(any(feature = "inbound-shadowsocks", feature = "outbound-shadowsocks"))] pub mod shadowsocks; +#[cfg(any(feature = "inbound-simplesocks"))] +pub mod simplesocks; #[cfg(any(feature = "inbound-socks", feature = "outbound-socks"))] pub mod socks; #[cfg(feature = "outbound-static")] diff --git a/leaf/src/proxy/simplesocks/inbound/datagram.rs b/leaf/src/proxy/simplesocks/inbound/datagram.rs new file mode 100644 index 000000000..e0bbec7ab --- /dev/null +++ b/leaf/src/proxy/simplesocks/inbound/datagram.rs @@ -0,0 +1,89 @@ +use std::convert::TryFrom; +use std::io; +use std::net::SocketAddr; + +use anyhow::anyhow; +use async_trait::async_trait; +use bytes::{BufMut, BytesMut}; + +use crate::{ + proxy::*, + session::{DatagramSource, SocksAddr, SocksAddrWireType}, +}; + +pub struct Handler; + +#[async_trait] +impl InboundDatagramHandler for Handler { + async fn handle<'a>(&'a self, socket: AnyInboundDatagram) -> io::Result { + Ok(InboundTransport::Datagram( + Box::new(Datagram { socket }), + None, + )) + } +} + +pub struct Datagram { + socket: Box, +} + +impl InboundDatagram for Datagram { + fn split( + self: Box, + ) -> ( + Box, + Box, + ) { + let (rh, sh) = self.socket.split(); + ( + Box::new(DatagramRecvHalf(rh)), + Box::new(DatagramSendHalf(sh)), + ) + } + + fn into_std(self: Box) -> io::Result { + self.socket.into_std() + } +} + +pub struct DatagramRecvHalf(Box); + +#[async_trait] +impl InboundDatagramRecvHalf for DatagramRecvHalf { + async fn recv_from( + &mut self, + buf: &mut [u8], + ) -> ProxyResult<(usize, DatagramSource, SocksAddr)> { + let mut recv_buf = vec![0u8; buf.len()]; + let (n, src_addr, _) = self.0.recv_from(&mut recv_buf).await?; + let dst_addr = SocksAddr::try_from((&recv_buf[0..], SocksAddrWireType::PortLast)) + .map_err(|e| ProxyError::DatagramWarn(anyhow!("Parse target address failed: {}", e)))?; + let header_size = dst_addr.size(); + let payload_size = n - header_size; + assert!(buf.len() >= payload_size); + (&mut buf[..payload_size]) + .copy_from_slice(&recv_buf[header_size..header_size + payload_size]); + Ok((payload_size, src_addr, dst_addr)) + } +} + +pub struct DatagramSendHalf(Box); + +#[async_trait] +impl InboundDatagramSendHalf for DatagramSendHalf { + async fn send_to( + &mut self, + buf: &[u8], + src_addr: &SocksAddr, + dst_addr: &SocketAddr, + ) -> io::Result { + let mut send_buf = BytesMut::new(); + src_addr.write_buf(&mut send_buf, SocksAddrWireType::PortLast); + send_buf.put_slice(buf); + self.0.send_to(&send_buf[..], src_addr, dst_addr).await + } + + async fn close(&mut self) -> io::Result<()> { + self.0.close().await + } +} diff --git a/leaf/src/proxy/simplesocks/inbound/mod.rs b/leaf/src/proxy/simplesocks/inbound/mod.rs new file mode 100644 index 000000000..8e5cfd1a2 --- /dev/null +++ b/leaf/src/proxy/simplesocks/inbound/mod.rs @@ -0,0 +1,5 @@ +mod datagram; +mod stream; + +pub use datagram::Handler as DatagramHandler; +pub use stream::Handler as StreamHandler; diff --git a/leaf/src/proxy/simplesocks/inbound/stream.rs b/leaf/src/proxy/simplesocks/inbound/stream.rs new file mode 100644 index 000000000..daf3ae114 --- /dev/null +++ b/leaf/src/proxy/simplesocks/inbound/stream.rs @@ -0,0 +1,27 @@ +use std::io; + +use async_trait::async_trait; +use bytes::{BufMut, BytesMut}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tracing::debug; + +use crate::{ + proxy::*, + session::{Session, SocksAddr, SocksAddrWireType}, +}; + +pub struct Handler; + +#[async_trait] +impl InboundStreamHandler for Handler { + async fn handle<'a>( + &'a self, + mut sess: Session, + mut stream: AnyStream, + ) -> std::io::Result { + let mut buf = BytesMut::new(); + let destination = SocksAddr::read_from(&mut stream, SocksAddrWireType::PortLast).await?; + sess.destination = destination; + Ok(InboundTransport::Stream(stream, sess)) + } +} diff --git a/leaf/src/proxy/simplesocks/mod.rs b/leaf/src/proxy/simplesocks/mod.rs new file mode 100644 index 000000000..612eebef7 --- /dev/null +++ b/leaf/src/proxy/simplesocks/mod.rs @@ -0,0 +1,2 @@ +#[cfg(feature = "inbound-simplesocks")] +pub mod inbound;