Skip to main content

proxifier_rs/
socks4.rs

1#![doc = include_str!("../SOCKS4.md")]
2use rustls::ClientConfig;
3use rustls_pki_types::ServerName;
4use std::{net::SocketAddrV4, sync::Arc};
5use tokio::{
6    io::{AsyncReadExt, AsyncWriteExt},
7    net::TcpStream,
8};
9use tokio_rustls::{TlsConnector, client::TlsStream};
10
11use crate::errors;
12static VERSION_4: u8 = 0x04;
13static CONNECT_REQUEST: u8 = 0x01;
14static NULL: u8 = 0x00;
15
16#[derive(Debug)]
17pub enum Response {
18    Granted = 90,
19    Failure = 91,
20    IdentFailure = 92,
21    IdentInvalid = 93,
22}
23
24impl TryFrom<u8> for Response {
25    type Error = errors::Error;
26
27    fn try_from(value: u8) -> Result<Self, Self::Error> {
28        match value {
29            90 => Ok(Response::Granted),
30            91 => Err(errors::Error::ProxyReply0x91),
31            92 => Err(errors::Error::ProxyReply0x92),
32            93 => Err(errors::Error::ProxyReply0x93),
33            _ => Err(errors::Error::ProxyResponseNotOk(
34                "unknown status reply from proxy server".into(),
35            )),
36        }
37    }
38}
39
40#[derive(Default)]
41pub struct Socks4 {
42    proxy: Option<SocketAddrV4>,
43    to: Option<SocketAddrV4>,
44}
45
46impl Socks4 {
47    pub fn new() -> Self {
48        Default::default()
49    }
50
51    pub fn proxy(mut self, ipv4: SocketAddrV4) -> Self {
52        self.proxy = Some(ipv4);
53        self
54    }
55
56    pub fn to(mut self, ipv4: SocketAddrV4) -> Self {
57        self.to = Some(ipv4);
58        self
59    }
60
61    pub async fn connect(&self) -> crate::Result<TcpStream> {
62        let proxy = self.proxy.ok_or(errors::Error::SocksProxyAddrNotSet)?;
63        let target = self.to.ok_or(errors::Error::SocksTargetAddrNotSet)?;
64
65        let mut conn = TcpStream::connect(proxy).await?;
66        let mut packet = [0u8; 9];
67
68        packet[0] = VERSION_4;
69        packet[1] = CONNECT_REQUEST;
70
71        packet[2..4].copy_from_slice(&target.port().to_be_bytes());
72        packet[4..8].copy_from_slice(&target.ip().octets());
73        packet[8] = NULL;
74
75        conn.write_all(&packet).await?;
76
77        let mut reply = [0u8; 8];
78        conn.read(&mut reply[..]).await?;
79
80        Response::try_from(reply[1])?;
81        Ok(conn)
82    }
83
84    pub async fn connect_tls(
85        &self,
86        config: Arc<ClientConfig>,
87        sni: ServerName<'static>,
88    ) -> crate::Result<TlsStream<TcpStream>> {
89        let conn = self.connect().await?;
90
91        let connector = TlsConnector::from(config);
92        let conn = connector.connect(sni, conn).await?;
93        Ok(conn)
94    }
95}