tun2proxy/src/socks5.rs

334 lines
9.8 KiB
Rust
Raw Normal View History

use crate::error::Error;
2022-08-01 14:36:58 +00:00
use crate::tun2proxy::{
2023-03-22 19:11:28 +01:00
Connection, ConnectionManager, Credentials, DestinationHost, IncomingDataEvent,
IncomingDirection, OutgoingDataEvent, OutgoingDirection, TcpProxy,
2022-08-01 14:36:58 +00:00
};
2021-09-02 11:30:23 +02:00
use std::collections::VecDeque;
use std::net::{IpAddr, SocketAddr};
#[derive(Eq, PartialEq, Debug)]
#[allow(dead_code)]
enum SocksState {
ClientHello,
ServerHello,
2023-03-22 01:02:27 +01:00
SendAuthData,
ReceiveAuthResponse,
2021-09-02 11:30:23 +02:00
SendRequest,
ReceiveResponse,
2022-08-01 14:36:58 +00:00
Established,
2021-09-02 11:30:23 +02:00
}
#[repr(u8)]
#[derive(Copy, Clone)]
enum SocksAddressType {
Ipv4 = 1,
DomainName = 3,
2022-08-01 14:36:58 +00:00
Ipv6 = 4,
2021-09-02 11:30:23 +02:00
}
#[allow(dead_code)]
enum SocksAuthentication {
None = 0,
2022-08-01 14:36:58 +00:00
Password = 2,
2021-09-02 11:30:23 +02:00
}
2021-09-02 21:02:17 +02:00
#[allow(dead_code)]
#[repr(u8)]
#[derive(Debug, Eq, PartialEq)]
enum SocksReplies {
Succeeded,
GeneralFailure,
ConnectionDisallowed,
NetworkUnreachable,
ConnectionRefused,
TtlExpired,
CommandUnsupported,
2022-08-01 14:36:58 +00:00
AddressUnsupported,
2021-09-02 21:02:17 +02:00
}
impl std::fmt::Display for SocksReplies {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
2023-03-22 01:02:27 +01:00
pub(crate) struct SocksConnection {
2021-09-02 11:30:23 +02:00
connection: Connection,
state: SocksState,
client_inbuf: VecDeque<u8>,
server_inbuf: VecDeque<u8>,
client_outbuf: VecDeque<u8>,
server_outbuf: VecDeque<u8>,
data_buf: VecDeque<u8>,
2023-03-22 01:02:27 +01:00
manager: std::rc::Rc<dyn ConnectionManager>,
2021-09-02 11:30:23 +02:00
}
impl SocksConnection {
2023-03-22 01:02:27 +01:00
pub fn new(connection: &Connection, manager: std::rc::Rc<dyn ConnectionManager>) -> Self {
2021-09-02 11:30:23 +02:00
let mut result = Self {
2023-03-22 19:11:28 +01:00
connection: connection.clone(),
2021-09-02 11:30:23 +02:00
state: SocksState::ServerHello,
client_inbuf: Default::default(),
server_inbuf: Default::default(),
client_outbuf: Default::default(),
server_outbuf: Default::default(),
data_buf: Default::default(),
2023-03-22 01:02:27 +01:00
manager,
2021-09-02 11:30:23 +02:00
};
2023-03-22 01:02:27 +01:00
result.send_client_hello();
2021-09-02 11:30:23 +02:00
result
}
2023-03-22 01:02:27 +01:00
fn send_client_hello(&mut self) {
let credentials = self.manager.get_credentials();
if credentials.is_some() {
2023-03-22 19:11:28 +01:00
self.server_outbuf
.extend(&[5u8, 1, SocksAuthentication::Password as u8]);
2023-03-22 01:02:27 +01:00
} else {
2023-03-22 19:11:28 +01:00
self.server_outbuf
.extend(&[5u8, 1, SocksAuthentication::None as u8]);
2023-03-22 01:02:27 +01:00
}
self.state = SocksState::ServerHello;
}
2021-09-02 11:30:23 +02:00
fn receive_server_hello(&mut self) -> Result<(), Error> {
2023-03-22 01:02:27 +01:00
if self.server_inbuf.len() < 2 {
return Ok(());
}
if self.server_inbuf[0] != 5 {
return Err("SOCKS server replied with an unexpected version.".into());
2023-03-22 01:02:27 +01:00
}
2021-09-02 21:02:17 +02:00
if self.server_inbuf[1] != 0 && self.manager.get_credentials().is_none()
|| self.server_inbuf[1] != 2 && self.manager.get_credentials().is_some()
2023-03-22 01:02:27 +01:00
{
return Err("SOCKS server requires an unsupported authentication method.".into());
2023-03-22 01:02:27 +01:00
}
2021-09-02 21:02:17 +02:00
2023-03-22 01:02:27 +01:00
self.server_inbuf.drain(0..2);
2021-09-02 11:30:23 +02:00
if self.manager.get_credentials().is_some() {
2023-03-22 01:02:27 +01:00
self.state = SocksState::SendAuthData;
} else {
self.state = SocksState::SendRequest;
}
self.state_change()
}
2021-09-02 11:30:23 +02:00
fn send_auth_data(&mut self) -> Result<(), Error> {
let tmp = Credentials::default();
let credentials = self.manager.get_credentials().as_ref().unwrap_or(&tmp);
2023-03-22 01:02:27 +01:00
self.server_outbuf
.extend(&[1u8, credentials.username.len() as u8]);
self.server_outbuf.extend(&credentials.username);
self.server_outbuf
.extend(&[credentials.password.len() as u8]);
self.server_outbuf.extend(&credentials.password);
self.state = SocksState::ReceiveAuthResponse;
self.state_change()
}
2021-09-02 21:02:17 +02:00
fn receive_auth_data(&mut self) -> Result<(), Error> {
2023-03-22 01:02:27 +01:00
if self.server_inbuf.len() < 2 {
return Ok(());
}
if self.server_inbuf[0] != 1 || self.server_inbuf[1] != 0 {
return Err("SOCKS authentication failed.".into());
2023-03-22 01:02:27 +01:00
}
self.server_inbuf.drain(0..2);
self.state = SocksState::SendRequest;
self.state_change()
}
2021-09-02 21:02:17 +02:00
fn receive_connection_status(&mut self) -> Result<(), Error> {
2023-03-22 01:02:27 +01:00
if self.server_inbuf.len() < 4 {
return Ok(());
}
let ver = self.server_inbuf[0];
let rep = self.server_inbuf[1];
let _rsv = self.server_inbuf[2];
let atyp = self.server_inbuf[3];
if ver != 5 {
return Err("SOCKS server replied with an unexpected version.".into());
2023-03-22 01:02:27 +01:00
}
2021-09-02 11:30:23 +02:00
2023-03-22 01:02:27 +01:00
if rep != 0 {
return Err("SOCKS connection unsuccessful.".into());
2023-03-22 01:02:27 +01:00
}
2021-09-02 11:30:23 +02:00
2023-03-22 01:02:27 +01:00
if atyp != SocksAddressType::Ipv4 as u8
&& atyp != SocksAddressType::Ipv6 as u8
&& atyp != SocksAddressType::DomainName as u8
{
return Err("SOCKS server replied with unrecognized address type.".into());
2023-03-22 01:02:27 +01:00
}
2021-09-02 11:30:23 +02:00
2023-03-22 01:02:27 +01:00
if atyp == SocksAddressType::DomainName as u8 && self.server_inbuf.len() < 5 {
return Ok(());
}
2021-09-02 11:30:23 +02:00
2023-03-22 01:02:27 +01:00
if atyp == SocksAddressType::DomainName as u8
&& self.server_inbuf.len() < 7 + (self.server_inbuf[4] as usize)
{
return Ok(());
}
2021-09-02 11:30:23 +02:00
2023-03-22 01:02:27 +01:00
let message_length = if atyp == SocksAddressType::Ipv4 as u8 {
10
} else if atyp == SocksAddressType::Ipv6 as u8 {
22
} else {
7 + (self.server_inbuf[4] as usize)
};
self.server_inbuf.drain(0..message_length);
self.server_outbuf.append(&mut self.data_buf);
self.data_buf.clear();
self.state = SocksState::Established;
self.state_change()
}
fn send_request(&mut self) -> Result<(), Error> {
2023-03-22 19:11:28 +01:00
self.server_outbuf.extend(&[5u8, 1, 0]);
match &self.connection.dst.host {
DestinationHost::Address(dst_ip) => {
let cmd = if dst_ip.is_ipv4() {
SocksAddressType::Ipv4
} else {
SocksAddressType::Ipv6
};
self.server_outbuf.extend(&[cmd as u8]);
match dst_ip {
IpAddr::V4(ip) => self.server_outbuf.extend(ip.octets().as_ref()),
IpAddr::V6(ip) => self.server_outbuf.extend(ip.octets().as_ref()),
};
}
DestinationHost::Hostname(_) => {
self.server_outbuf
.extend(&[SocksAddressType::DomainName as u8]);
}
}
2023-03-22 01:02:27 +01:00
self.server_outbuf.extend(&[
2023-03-22 19:11:28 +01:00
(self.connection.dst.port >> 8) as u8,
(self.connection.dst.port & 0xff) as u8,
2023-03-22 01:02:27 +01:00
]);
self.state = SocksState::ReceiveResponse;
self.state_change()
}
pub fn state_change(&mut self) -> Result<(), Error> {
2023-03-22 01:02:27 +01:00
match self.state {
SocksState::ServerHello => self.receive_server_hello(),
SocksState::SendAuthData => self.send_auth_data(),
SocksState::ReceiveAuthResponse => self.receive_auth_data(),
SocksState::SendRequest => self.send_request(),
SocksState::ReceiveResponse => self.receive_connection_status(),
2021-09-02 11:30:23 +02:00
SocksState::Established => {
2021-09-02 21:02:17 +02:00
self.client_outbuf.extend(self.server_inbuf.iter());
self.server_outbuf.extend(self.client_inbuf.iter());
self.server_inbuf.clear();
self.client_inbuf.clear();
2023-03-22 01:02:27 +01:00
Ok(())
2021-09-02 11:30:23 +02:00
}
2023-03-22 01:02:27 +01:00
_ => Ok(()),
2021-09-02 11:30:23 +02:00
}
}
}
impl TcpProxy for SocksConnection {
fn push_data(&mut self, event: IncomingDataEvent<'_>) -> Result<(), Error> {
2021-09-02 11:30:23 +02:00
let direction = event.direction;
let buffer = event.buffer;
match direction {
IncomingDirection::FromServer => {
self.server_inbuf.extend(buffer.iter());
2022-08-01 14:36:58 +00:00
}
2021-09-02 11:30:23 +02:00
IncomingDirection::FromClient => {
if self.state == SocksState::Established {
self.client_inbuf.extend(buffer.iter());
} else {
self.data_buf.extend(buffer.iter());
}
}
}
2021-09-02 21:02:17 +02:00
self.state_change()
2021-09-02 11:30:23 +02:00
}
fn consume_data(&mut self, dir: OutgoingDirection, size: usize) {
2022-08-01 14:36:58 +00:00
let buffer = if dir == OutgoingDirection::ToServer {
2021-09-02 11:30:23 +02:00
&mut self.server_outbuf
} else {
&mut self.client_outbuf
};
buffer.drain(0..size);
}
fn peek_data(&mut self, dir: OutgoingDirection) -> OutgoingDataEvent {
let buffer = if dir == OutgoingDirection::ToServer {
&mut self.server_outbuf
} else {
&mut self.client_outbuf
};
2022-08-01 14:36:58 +00:00
OutgoingDataEvent {
2021-09-02 11:30:23 +02:00
direction: dir,
2022-08-01 14:36:58 +00:00
buffer: buffer.make_contiguous(),
}
2021-09-02 11:30:23 +02:00
}
2021-09-02 21:02:17 +02:00
fn connection_established(&self) -> bool {
2022-08-01 14:36:58 +00:00
self.state == SocksState::Established
2021-09-02 21:02:17 +02:00
}
2021-09-02 11:30:23 +02:00
}
pub struct Socks5Manager {
server: std::net::SocketAddr,
credentials: Option<Credentials>,
2021-09-02 11:30:23 +02:00
}
impl ConnectionManager for Socks5Manager {
fn handles_connection(&self, connection: &Connection) -> bool {
connection.proto == smoltcp::wire::IpProtocol::Tcp.into()
}
2023-03-22 01:02:27 +01:00
fn new_connection(
&self,
connection: &Connection,
manager: std::rc::Rc<dyn ConnectionManager>,
) -> Option<std::boxed::Box<dyn TcpProxy>> {
2021-09-02 11:30:23 +02:00
if connection.proto != smoltcp::wire::IpProtocol::Tcp.into() {
return None;
}
2023-03-22 01:02:27 +01:00
Some(std::boxed::Box::new(SocksConnection::new(
connection, manager,
)))
2021-09-02 11:30:23 +02:00
}
2023-03-21 01:08:44 +01:00
fn close_connection(&self, _: &Connection) {}
2021-09-02 11:30:23 +02:00
fn get_server(&self) -> SocketAddr {
self.server
}
2023-03-22 01:02:27 +01:00
fn get_credentials(&self) -> &Option<Credentials> {
2023-03-22 01:02:27 +01:00
&self.credentials
}
2021-09-02 11:30:23 +02:00
}
impl Socks5Manager {
pub fn new(server: SocketAddr, credentials: Option<Credentials>) -> std::rc::Rc<Self> {
2023-03-22 01:02:27 +01:00
std::rc::Rc::new(Self {
2021-09-02 11:30:23 +02:00
server,
2023-03-22 01:02:27 +01:00
credentials,
})
2021-09-02 11:30:23 +02:00
}
2022-08-01 14:36:58 +00:00
}