socken5/
lib.rs

1//! Socks5 protocol structure
2//!
3//! Socken5 provides an incomplete protocol structure for the socks5 protocol.
4//!
5//! # Usage
6//! ```toml
7//! [dependencies]
8//! socken5 = "0.1.0"
9//! ```
10
11use async_trait::async_trait;
12use tokio::io::{AsyncReadExt, AsyncWriteExt};
13
14use std::result;
15use std::net::{Ipv4Addr, Ipv6Addr};
16
17// Public modules
18/// Downstream packets.
19pub mod downstream;
20mod error;
21/// Upstream packets.
22pub mod upstream;
23
24// Public exports
25pub use crate::error::{Result, Error};
26
27const VERSION: u8 = 0x05;
28
29#[async_trait]
30pub trait AsyncWrite {
31    async fn write<W>(&self, buf: &mut W) -> Result<()> where W: AsyncWriteExt + Unpin + Send;
32}
33
34#[async_trait]
35pub trait AsyncRead: Sized {
36    async fn read<R>(buf: &mut R) -> Result<Self> where R: AsyncReadExt + Unpin + Send;
37}
38
39/// A socks5 method.
40#[derive(Clone, Copy, PartialEq, Eq, Debug)]
41pub enum Method {
42    /// No authentication.
43    NoAuth,
44    /// Gssapi authentication.
45    Gssapi,
46    /// Username/Password authentication.
47    Auth,
48    /// Other methods.
49    Other(u8),
50    /// No acceptable method found.
51    NoAcceptable,
52}
53
54impl From<u8> for Method {
55    fn from(val: u8) -> Self {
56        match val {
57            0x00 => Self::NoAuth,
58            0x01 => Self::Gssapi,
59            0x02 => Self::Auth,
60            _ => Self::Other(val),
61        }
62    }
63}
64
65impl From<Method> for u8 {
66    fn from(method: Method) -> Self {
67        match method {
68            Method::NoAuth => 0x00,
69            Method::Gssapi => 0x01,
70            Method::Auth => 0x02,
71            Method::Other(val) => val,
72            Method::NoAcceptable => 0xFF,
73        }
74    }
75}
76
77/// A socks5 command.
78#[derive(Clone, Copy, PartialEq, Eq, Debug)]
79pub enum Command {
80    /// Connect to target.
81    Connect,
82    /// Bind to socket.
83    Bind,
84    /// Associate Udp.
85    UdpAssociate,
86}
87
88impl TryFrom<u8> for Command {
89    type Error = Error;
90
91    fn try_from(val: u8) -> result::Result<Self, Self::Error> {
92        match val {
93            0x01 => Ok(Self::Connect),
94            0x02 => Ok(Self::Bind),
95            0x03 => Ok(Self::UdpAssociate),
96            _ => Err(Error::InvalidCommand)
97        }
98    }
99}
100
101impl From<Command> for u8 {
102    fn from(cmd: Command) -> Self {
103        match cmd {
104            Command::Connect => 0x01,
105            Command::Bind => 0x02,
106            Command::UdpAssociate => 0x03,
107        }
108    }
109}
110
111/// An address type, either IPv4, IPv6 or domain name.
112#[derive(Clone, PartialEq, Eq, Debug)]
113pub enum Addr {
114    /// An IPv4 address.
115    V4(Ipv4Addr),
116    /// A domain domain name.
117    Domain(String),
118    /// An IPv6 address.
119    V6(Ipv6Addr),
120}
121
122/// A socks5 command reply.
123#[derive(Clone, Copy, PartialEq, Eq, Debug)]
124pub enum Reply {
125    /// Successful.
126    Success,
127    /// Internal server error.
128    ServerFailure,
129    /// Connection not allowed by ruleset.
130    NotAllowedByRuleset,
131    /// Network unreachable.
132    NetworkUnreachable,
133    /// Host unreachable.
134    HostUnreachable,
135    /// Connection refused.
136    ConnectionRefused,
137    /// Ttl expired.
138    TtlExpired,
139    /// Command not supported.
140    CommandNotSupported,
141    /// Address type not supported.
142    AddrTypeNotSupported,
143}
144
145impl From<Reply> for u8 {
146    fn from(reply: Reply) -> Self {
147        match reply {
148            Reply::Success => 0x00,
149            Reply::ServerFailure => 0x01,
150            Reply::NotAllowedByRuleset => 0x02,
151            Reply::NetworkUnreachable => 0x03,
152            Reply::HostUnreachable => 0x04,
153            Reply::ConnectionRefused => 0x05,
154            Reply::TtlExpired => 0x06,
155            Reply::CommandNotSupported => 0x07,
156            Reply::AddrTypeNotSupported => 0x08,
157        }
158    }
159}