rusnel/common/
socks.rs

1use std::net::Ipv4Addr;
2
3use quinn::{Connection, RecvStream, SendStream};
4use tokio::io::{AsyncReadExt, AsyncWriteExt};
5use tokio::net::{TcpListener, TcpStream};
6use tracing::{error, info};
7
8use crate::common::remote;
9use crate::verbose;
10
11use super::remote::RemoteRequest;
12use super::tcp::tunnel_tcp_stream;
13use super::tunnel::{client_send_remote_request, client_send_remote_start};
14use anyhow::{anyhow, Result};
15
16pub async fn tunnel_socks_client(quic_connection: Connection, remote: RemoteRequest) -> Result<()> {
17    let local_addr = format!("{}:{}", remote.local_host, remote.local_port);
18    let listener = TcpListener::bind(&local_addr).await?;
19    info!("SOCKS5 proxy listening on {}", &local_addr);
20
21    loop {
22        let (mut local_conn, local_addr) = listener.accept().await?;
23        let connection = quic_connection.clone();
24        let remote = remote.clone();
25
26        tokio::spawn(async move {
27            let dynamic_remote = socks_handshake(&mut local_conn, &remote).await;
28            match dynamic_remote {
29                Err(e) => error!("Error handshaking with client {}: {}", local_addr, e),
30                Ok(dynamic_remote) => {
31                    tokio::spawn(async move {
32                        let (send, recv) = match connection.open_bi().await {
33                            Ok(stream) => stream,
34                            Err(e) => {
35                                error!("Failed to open bi connection: {}", e);
36                                return;
37                                // return Err(anyhow!("Failed to open bi connection: {}", e))
38                            }
39                        };
40                        match start_client_dynamic_tunnel(local_conn, send, recv, dynamic_remote)
41                            .await
42                        {
43                            Ok(()) => (),
44                            Err(e) => {
45                                error!("Failed to start dynamic remote: {}", e);
46                            }
47                        };
48                    });
49                }
50            }
51        })
52        .await?;
53    }
54}
55
56async fn start_client_dynamic_tunnel(
57    mut socks_conn: TcpStream,
58    mut send_channel: SendStream,
59    mut recv_channel: RecvStream,
60    dynamic_remote: RemoteRequest,
61) -> Result<()> {
62    client_send_remote_request(&dynamic_remote, &mut send_channel, &mut recv_channel).await?;
63    client_send_remote_start(&mut send_channel, dynamic_remote).await?;
64
65    // Respond to the application with success
66    socks_conn
67        .write_all(&[0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0])
68        .await?;
69
70    tunnel_tcp_stream(socks_conn, send_channel, recv_channel).await?;
71
72    Ok(())
73}
74
75// TODO - support udp over socks5 :)
76/// perfomrs socks handshake with application and returns a new dynamic remote request
77async fn socks_handshake(
78    conn: &mut TcpStream,
79    original_remote: &RemoteRequest,
80) -> Result<RemoteRequest> {
81    // Step 1: SOCKS5 handshake
82    let mut buf = [0u8; 256];
83    conn.read_exact(&mut buf[..2]).await?;
84
85    if buf[0] != 0x05 {
86        eprintln!("Unsupported SOCKS version: {}", buf[0]);
87        return Err(anyhow!("Unsupported SOCKS version: {}", buf[0]));
88    }
89
90    let methods_len = buf[1] as usize;
91    conn.read_exact(&mut buf[..methods_len]).await?;
92
93    // Only support "no authentication" (0x00)
94    conn.write_all(&[0x05, 0x00]).await?;
95
96    // Step 2: Read SOCKS5 request
97    conn.read_exact(&mut buf[..4]).await?;
98
99    if buf[1] != 0x01 {
100        eprintln!("Unsupported command: {}", buf[1]);
101        conn.write_all(&[0x05, 0x07]).await?; // Command not supported
102        return Err(anyhow!("Unsupported SOCKS command: {}", buf[1]));
103    }
104
105    // Step 3: Parse address and port
106    let dynamic_remote = match buf[3] {
107        0x01 => {
108            // IPv4
109            let mut addr = [0u8; 4];
110            conn.read_exact(&mut addr).await?;
111            let mut port = [0u8; 2];
112            conn.read_exact(&mut port).await?;
113            let port = u16::from_be_bytes(port);
114            let remote_address = Ipv4Addr::from(addr).to_string();
115            RemoteRequest::new(
116                original_remote.local_host,
117                original_remote.local_port,
118                remote_address,
119                port,
120                original_remote.reversed,
121                remote::Protocol::Tcp,
122            )
123        }
124        0x03 => {
125            // Domain name
126            let mut len = [0u8; 1];
127            conn.read_exact(&mut len).await?;
128            let mut domain = vec![0u8; len[0] as usize];
129            conn.read_exact(&mut domain).await?;
130            let mut port = [0u8; 2];
131            conn.read_exact(&mut port).await?;
132            let port = u16::from_be_bytes(port);
133            let domain = String::from_utf8_lossy(&domain).into_owned();
134            RemoteRequest::new(
135                original_remote.local_host,
136                original_remote.local_port,
137                domain,
138                port,
139                original_remote.reversed,
140                remote::Protocol::Tcp,
141            )
142        }
143        _ => {
144            eprintln!("Unsupported address type: {}", buf[3]);
145            conn.write_all(&[0x05, 0x08]).await?; // Address type not supported
146            return Err(anyhow!("Unsupported address type: {}", buf[3]));
147        }
148    };
149
150    verbose!("Creating dynamic remote: {:?}", dynamic_remote);
151
152    Ok(dynamic_remote)
153}