simple_server/
simple_server.rs1use simple_socks5::conn::request::CMD;
2use simple_socks5::{ATYP, Socks5, conn::reply::Rep, error::SocksError, parse::AddrPort};
3use std::net::{IpAddr, Ipv4Addr};
4use std::sync::Arc;
5use tokio::io;
6use tokio::io::AsyncWriteExt;
7use tokio::net::TcpStream;
8use tracing::{error, info, warn};
9
10#[tokio::main]
11async fn main() -> Result<(), SocksError> {
12 tracing_subscriber::fmt()
13 .with_target(false)
14 .with_level(true)
15 .compact()
16 .init();
17
18 let mut server = Socks5::bind("127.0.0.1:1080").await?;
20 server.allow_no_auth();
21
22 let server = Arc::new(server);
26
27 info!("SOCKS5 proxy listening on {}", server.local_addr()?);
28
29 loop {
30 let (client, addr) = server.accept().await?;
31 let server_ref = Arc::clone(&server);
32
33 tokio::spawn(async move {
34 if let Err(e) = handle_client(server_ref, client, addr).await {
35 error!("Client {addr} error: {e}");
36 }
37 });
38 }
39}
40
41async fn handle_client(
42 server: Arc<Socks5>,
43 mut stream: TcpStream,
44 addr: std::net::SocketAddr,
45) -> Result<(), SocksError> {
46 info!("New client connected from {addr}");
47
48 if let Err(e) = server.authenticate(&mut stream).await {
49 warn!("Authentication failed for {addr}: {e}");
50 let _ = stream.shutdown().await;
51 return Ok(());
52 }
53 info!("Authentication succeeded for {addr}");
54
55 let req = match Socks5::read_conn_request(&mut stream).await {
56 Ok(r) => {
57 info!(client=%addr, "Connection request");
58 info!(request=%r, "Request format");
59 r
60 }
61 Err(e) => {
62 error!("Failed to read connection request from {addr}: {e}");
63 let _ = stream.shutdown().await;
64 return Ok(());
65 }
66 };
67
68 match req.cmd {
69 CMD::Connect => {
70 info!(client=%addr, dest=%req.dst, "Connecting to destination");
71
72 let mut target = match req.dst {
73 AddrPort::V4(ip, port) => TcpStream::connect((ip, port)).await?,
74 AddrPort::V6(ip, port) => TcpStream::connect((ip, port)).await?,
75 AddrPort::Domain(ref host, port) => {
76 TcpStream::connect((host.as_str(), port)).await?
77 }
78 };
79
80 let local_addr = target.local_addr()?;
81 let bnd = match local_addr.ip() {
82 IpAddr::V4(ip) => AddrPort::V4(ip, local_addr.port()),
83 IpAddr::V6(ip) => AddrPort::V6(ip, local_addr.port()),
84 };
85
86 let atyp = match bnd {
87 AddrPort::V4(_, _) => ATYP::V4,
88 AddrPort::V6(_, _) => ATYP::V6,
89 _ => ATYP::DomainName,
90 };
91
92 info!(client=%addr, bind=%bnd, atyp=%atyp, "Connection established");
93
94 Socks5::send_conn_reply(&mut stream, Rep::Succeeded, atyp, bnd).await?;
95
96 if let Err(e) = io::copy_bidirectional(&mut stream, &mut target).await {
97 warn!("TCP connection with {addr} closed with error: {e}");
98 } else {
99 info!("TCP connection with {addr} closed");
100 }
101 }
102
103 _ => {
104 warn!("Unsupported command from {addr}: {}", req.cmd);
105 Socks5::send_conn_reply(
106 &mut stream,
107 Rep::CommandNotSupported,
108 ATYP::V4,
109 AddrPort::V4(Ipv4Addr::UNSPECIFIED, 0),
110 )
111 .await?;
112 }
113 }
114
115 Ok(())
116}