Skip to content

Commit

Permalink
Adding necessary documentation for sock 5 version
Browse files Browse the repository at this point in the history
  • Loading branch information
anmolbhatia05 committed Sep 27, 2023
1 parent 27bc870 commit 40b2769
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 33 deletions.
46 changes: 36 additions & 10 deletions socksx/src/socks5/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use crate::addresses::{self, Address};
use crate::constants::*;
use anyhow::Result;
use num_traits::FromPrimitive;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};

mod s5_client;
mod s5_handler;

pub use s5_client::Socks5Client;
pub use s5_handler::Socks5Handler;

use crate::addresses::{self, Address};
use crate::constants::*;

mod s5_client;
mod s5_handler;

/// Represents the different commands for SOCKS5 protocol.
#[repr(u8)]
#[derive(Clone, Debug, FromPrimitive, PartialEq)]
pub enum Socks5Command {
Expand All @@ -18,16 +20,24 @@ pub enum Socks5Command {
UdpAssociate = 0x03,
}

/// Represents a SOCKS5 request.
#[derive(Clone, Debug)]
pub struct Socks5Request {
pub command: Socks5Command,
pub destination: Address,
}

impl Socks5Request {
/// Creates a new SOCKS5 request.
///
/// # Arguments
///
/// * `command` - The command type (e.g., Connect).
/// * `destination` - The target address and port to connect to.
///
/// # Returns
///
/// A new `Socks5Request` instance.
pub fn new(
command: u8,
destination: Address,
Expand All @@ -38,9 +48,11 @@ impl Socks5Request {
}
}

/// Converts the request into bytes suitable for transmission over a SOCKS5 connection.
///
/// # Returns
///
///
/// A vector of bytes representing the request.
pub fn into_socks_bytes(self) -> Vec<u8> {
let mut data = vec![SOCKS_VER_5, SOCKS_CMD_CONNECT, SOCKS_RSV];
data.extend(self.destination.as_socks_bytes());
Expand All @@ -49,6 +61,7 @@ impl Socks5Request {
}
}

/// Represents different reply codes for SOCKS5 protocol.
#[repr(u8)]
#[derive(Clone, Debug, FromPrimitive, PartialEq)]
pub enum Socks5Reply {
Expand All @@ -64,15 +77,22 @@ pub enum Socks5Reply {
ConnectionAttemptTimeOut = 0x09,
}

/// Writes a SOCKS5 reply to the provided stream.
///
/// # Arguments
///
/// * `stream` - The output stream where the reply will be written.
/// * `reply` - The SOCKS5 reply code to be written.
///
/// # Returns
///
/// A `Result` indicating success or an error.
pub async fn write_reply<S>(
stream: &mut S,
reply: Socks5Reply,
) -> Result<()>
where
S: AsyncWrite + Unpin,
where
S: AsyncWrite + Unpin,
{
let reply = [
SOCKS_VER_5,
Expand All @@ -92,12 +112,18 @@ where
Ok(())
}

/// Reads a SOCKS5 reply from the provided stream and returns the associated address.
///
/// # Arguments
///
/// * `stream` - The input stream where the reply will be read from.
///
/// # Returns
///
/// A `Result` containing the address associated with the reply if successful, or an error if the reply indicates failure.
pub async fn read_reply<S>(stream: &mut S) -> Result<Address>
where
S: AsyncRead + Unpin,
where
S: AsyncRead + Unpin,
{
let mut operation_reply = [0; 3];
stream.read_exact(&mut operation_reply).await?;
Expand Down
57 changes: 40 additions & 17 deletions socksx/src/socks5/s5_client.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
use crate::socks5::{self, Socks5Request};
use crate::{constants::*, Address, Credentials};
use anyhow::Result;
use std::convert::TryInto;
use std::net::SocketAddr;

use anyhow::Result;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;

use crate::{Address, constants::*, Credentials};
use crate::socks5::{self, Socks5Request};

/// Represents a SOCKS5 client for connecting to proxy servers.
#[derive(Clone)]
pub struct Socks5Client {
proxy_addr: SocketAddr,
credentials: Option<Credentials>,
}

impl Socks5Client {
/// Creates a new `Socks5Client`.
///
/// # Arguments
///
/// * `proxy_addr` - The address of the SOCKS5 proxy server.
/// * `credentials` - Optional SOCKS5 authentication credentials.
///
/// # Returns
///
/// A `Result` containing the new `Socks5Client` instance.
pub async fn new<A: Into<String>>(
proxy_addr: A,
credentials: Option<Credentials>,
Expand All @@ -28,17 +38,21 @@ impl Socks5Client {
})
}

/// ...
/// ...
/// ...
/// Establishes a SOCKS5 connection to the specified destination.
///
/// # Arguments
///
/// [rfc1928] https://tools.ietf.org/html/rfc1928
/// * `destination` - The target address and port to connect to.
///
/// # Returns
///
/// A `Result` containing a tuple with a `TcpStream` to the destination and the bound address.
pub async fn connect<A>(
&self,
destination: A,
) -> Result<(TcpStream, Address)>
where
A: TryInto<Address, Error = anyhow::Error>,
where
A: TryInto<Address, Error = anyhow::Error>,
{
if let Some(Credentials { username, password }) = &self.credentials {
ensure!(username.len() > 255, "Username MUST NOT be larger than 255 bytes.");
Expand Down Expand Up @@ -70,11 +84,15 @@ impl Socks5Client {
Ok((stream, binding))
}

/// ...
/// ...
/// ...
/// Negotiates the SOCKS5 authentication method with the proxy server.
///
/// # Arguments
///
/// * `stream` - The TCP stream connected to the proxy server.
///
/// [rfc1928] https://tools.ietf.org/html/rfc1928
/// # Returns
///
/// A `Result` containing the selected authentication method.
async fn negotiate_auth_method(
&self,
stream: &mut TcpStream,
Expand Down Expand Up @@ -110,11 +128,16 @@ impl Socks5Client {
}
}

/// ...
/// ...
/// ...
/// Authenticates with the SOCKS5 proxy using the provided credentials.
///
/// # Arguments
///
/// * `stream` - The TCP stream connected to the proxy server.
/// * `credentials` - The authentication credentials.
///
/// # Returns
///
/// [rfc1929] https://tools.ietf.org/html/rfc1929
/// A `Result` indicating success or an error if authentication fails.
async fn authenticate(
&self,
stream: &mut TcpStream,
Expand Down
38 changes: 32 additions & 6 deletions socksx/src/socks5/s5_handler.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use crate::addresses::{self, ProxyAddress};
use crate::socks5::{self, Socks5Reply};
use crate::SocksHandler;
use crate::{constants::*, Credentials};
use anyhow::Result;
use async_trait::async_trait;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;

use crate::{constants::*, Credentials};
use crate::addresses::{self, ProxyAddress};
use crate::socks5::{self, Socks5Reply};
use crate::SocksHandler;

/// Represents a SOCKS5 handler for processing client requests.
#[derive(Clone)]
pub struct Socks5Handler {
credentials: Option<Credentials>,
chain: Vec<ProxyAddress>,
//chain: Vec<ProxyAddress>,
}

impl Default for Socks5Handler {
Expand All @@ -20,22 +22,34 @@ impl Default for Socks5Handler {
}

impl Socks5Handler {
/// Creates a new `Socks5Handler` with an optional list of proxy addresses.
///
/// # Arguments
///
/// * `chain` - A vector of `ProxyAddress` instances representing proxy servers in a chain.
///
/// # Returns
///
/// A new `Socks5Handler` instance.
pub fn new(chain: Vec<ProxyAddress>) -> Self {
Socks5Handler {
credentials: None,
chain,
//chain,
}
}
}

#[async_trait]
impl SocksHandler for Socks5Handler {
/// Accepts a SOCKS5 client request and sets up a bidirectional connection.
///
/// # Arguments
///
/// * `source` - The TCP stream representing the client connection.
///
/// # Returns
///
/// A `Result` indicating success or an error.
async fn accept_request(
&self,
source: &mut TcpStream,
Expand All @@ -48,9 +62,15 @@ impl SocksHandler for Socks5Handler {
Ok(())
}

/// Refuses a SOCKS5 client request and notifies the client.
///
/// # Arguments
///
/// * `source` - The TCP stream representing the client connection.
///
/// # Returns
///
/// A `Result` indicating success or an error.
async fn refuse_request(
&self,
source: &mut TcpStream,
Expand All @@ -61,9 +81,15 @@ impl SocksHandler for Socks5Handler {
Ok(())
}

/// Sets up the SOCKS5 connection with a client.
///
/// # Arguments
///
/// * `source` - The TCP stream representing the client connection.
///
/// # Returns
///
/// A `Result` containing a TCP stream representing the destination connection.
async fn setup(
&self,
source: &mut TcpStream,
Expand Down

0 comments on commit 40b2769

Please sign in to comment.