async_proxies/proxies/socks4/
no_ident.rs

1use crate::proxy::AsyncProxy;
2use crate::proxies::socks4::general::{Command, ErrorKind};
3use async_trait::async_trait;
4
5use tokio::io::{AsyncReadExt, AsyncWriteExt};
6use tokio::net::TcpStream;
7use tokio::time::timeout;
8
9use std::net::SocketAddr;
10use std::net::SocketAddrV4;
11use std::time::Duration;
12
13pub struct Socks4NoIdent;
14
15pub struct Timeouts {
16    connection_timeout: Duration,
17    write_timeout: Duration,
18    read_timeout: Duration
19}
20
21pub struct ConnParams {
22    // the address of a proxy
23    socks_addr: SocketAddr,
24    // the address of a destination service
25    dest_addr: SocketAddrV4,
26    // the way to establish connection (bind a port/connect)
27    command: Command,
28    timeouts: Timeouts
29}
30
31impl Timeouts {
32    pub fn new(connection_timeout: Duration,
33               write_timeout: Duration,
34               read_timeout: Duration)
35        -> Timeouts
36    {
37        Timeouts { connection_timeout, write_timeout, read_timeout }
38    }
39}
40
41impl ConnParams {
42    pub fn new(socks_addr: SocketAddr, dest_addr: SocketAddrV4,
43        command: Command, timeouts: Timeouts)
44        -> ConnParams
45    {
46        ConnParams { socks_addr, dest_addr, command, timeouts }
47    }
48}
49
50#[async_trait]
51impl AsyncProxy for Socks4NoIdent {
52    type OutputStream = TcpStream;
53    type ErrorKind = ErrorKind;
54    type ConnParams = ConnParams;
55
56    async fn connect(&mut self, params: Self::ConnParams)
57        -> Result<Self::OutputStream, Self::ErrorKind>
58    {
59        // Connecting to the proxy itself
60        let future = TcpStream::connect(params.socks_addr);
61        let future = timeout(params.timeouts.connection_timeout, future);
62        // You also can see that this code template
63        // (with creating a future and wrapping it with a timeout)
64        // repeats many times in this code. The repetitions
65        // will be ofc reduced, don't worry.
66        let stream = future.await
67                           .map_err(|_| ErrorKind::OperationTimeoutReached)?
68                           .map_err(|_| ErrorKind::ConnectionFailed)?;
69        
70        // Buffer length in bytes is determined this way:
71        //  (+1) for the number of the version of the socks protocol (4 in this case)
72        //  (+1) for the command number (1 or 2)
73        //  (+2) for port (in the network byte order)
74        //  (+4) for the IPv4 address
75        //  (+n) where `n` is the length of the given ident
76        //  (+1) for the NULL-termination byte (0x00)
77        const BUFFER_LEN: usize = 1 + 1 + 2 + 4 + 1;
78        let mut buffer = Vec::with_capacity(BUFFER_LEN);
79
80        // the version of the socks protocol being used
81        buffer.push(4);
82        // the command number
83        buffer.push(params.command as u8);
84            
85        let port_in_bytes = params.dest_addr.port().to_be_bytes();
86        // the destination port
87        buffer.extend_from_slice(&port_in_bytes[..]);
88
89        let ipaddr_in_bytes = params.dest_addr.ip().octets();
90        // the ipv4 address of the destination host
91        buffer.extend_from_slice(&ipaddr_in_bytes[..]);
92
93        // the NULL-termination byte
94        buffer.push(0);
95            
96        let future = self.write_buffer(&buffer[..], stream);
97        let future = timeout(params.timeouts.write_timeout, future);
98        let mut stream = future.await
99                               .map_err(|_| ErrorKind::OperationTimeoutReached)??;
100
101        let future = stream.read(&mut buffer[..]);
102        let future = timeout(params.timeouts.read_timeout, future);
103        let read_bytes = future.await
104                               .map_err(|_| ErrorKind::OperationTimeoutReached)?
105                               .map_err(|e| ErrorKind::RawStreamIOFailed(e))?;
106
107        if read_bytes < 2 {
108            return Err(ErrorKind::GotBadBuffer)
109        }
110
111        match buffer[1] {
112            0x5a => Ok(stream),
113            0x5b => Err(ErrorKind::RequestDenied),
114            0x5c => Err(ErrorKind::IdentIsUnavailable),
115            0x5d => Err(ErrorKind::BadIdent),
116            _ => Err(ErrorKind::GotBadBuffer)
117        }
118    }
119
120    async fn write_buffer(&mut self, buffer: &[u8], mut stream: Self::OutputStream)
121        -> Result<Self::OutputStream, Self::ErrorKind>
122    {
123        match stream.write_all(buffer).await {
124            Ok(_) => Ok(stream),
125            Err(e) => Err(ErrorKind::RawStreamIOFailed(e))
126        }
127
128        // also could be written as:
129        //  stream.write_all(buffer)
130        //         .await
131        //         .map(|_| stream)
132        //         .map_err(|e| ErrorKind::RawStreamIOFailed(e))
133    }
134
135    async fn read_buffer(&mut self, buffer: &mut [u8], mut stream: Self::OutputStream)
136        -> Result<Self::OutputStream, Self::ErrorKind>
137    {
138        match stream.read(buffer).await {
139            Ok(_) => Ok(stream),
140            Err(e) => Err(ErrorKind::RawStreamIOFailed(e))
141        }
142    }
143
144    async fn drop_stream(&mut self, _: Self::OutputStream)
145        -> Result<(), Self::ErrorKind>
146    {
147        Ok(())
148    }
149}