Library code organized and restructured
This commit is contained in:
parent
65e781971d
commit
89557a711f
5 changed files with 568 additions and 479 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "sslrelay"
|
name = "sslrelay"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
authors = ["PinkP4nther <pinkp4nther@protonmail.com>"]
|
authors = ["PinkP4nther <pinkp4nther@protonmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
|
|
||||||
301
src/data.rs
301
src/data.rs
|
|
@ -1,38 +1,18 @@
|
||||||
use std::time::Duration;
|
use crate::{
|
||||||
use openssl::ssl::{SslConnector, SslMethod, SslStream, SslVerifyMode};
|
DownStreamInner,
|
||||||
use std::io::{self, Read, Write};
|
UpStreamInner,
|
||||||
use std::net::{TcpStream, Shutdown};
|
FullDuplexTcpState,
|
||||||
use std::sync::mpsc::{self, Receiver, Sender};
|
DataPipe,
|
||||||
use std::thread;
|
DataStreamType,
|
||||||
use std::result::Result;
|
Sender,
|
||||||
use std::sync::{Arc, Mutex};
|
Receiver,
|
||||||
|
|
||||||
use crate::{HandlerCallbacks, CallbackRet, InnerHandlers, TCPDataType};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum FullDuplexTcpState {
|
|
||||||
DownStreamWrite(Vec<u8>),
|
|
||||||
UpStreamWrite(Vec<u8>),
|
|
||||||
DownStreamShutDown,
|
|
||||||
UpStreamShutDown,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum DataPipe {
|
|
||||||
DataWrite(Vec<u8>),
|
|
||||||
Shutdown,
|
Shutdown,
|
||||||
}
|
mpsc,
|
||||||
|
Duration,
|
||||||
pub enum DataStreamType {
|
Read,
|
||||||
RAW(TcpStream),
|
Write,
|
||||||
TLS(SslStream<TcpStream>),
|
io,
|
||||||
}
|
};
|
||||||
|
|
||||||
struct DownStreamInner
|
|
||||||
{
|
|
||||||
ds_stream: DataStreamType,
|
|
||||||
internal_data_buffer: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DownStreamInner {
|
impl DownStreamInner {
|
||||||
|
|
||||||
|
|
@ -248,11 +228,6 @@ impl DownStreamInner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UpStreamInner
|
|
||||||
{
|
|
||||||
us_stream: DataStreamType,
|
|
||||||
internal_data_buffer: Vec<u8>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UpStreamInner {
|
impl UpStreamInner {
|
||||||
|
|
||||||
|
|
@ -456,252 +431,4 @@ impl UpStreamInner {
|
||||||
}
|
}
|
||||||
return Some(data_length);
|
return Some(data_length);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct FullDuplexTcp<H>
|
|
||||||
where
|
|
||||||
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static,
|
|
||||||
{
|
|
||||||
remote_host: String,
|
|
||||||
remote_port: String,
|
|
||||||
ds_inner_m: Arc<Mutex<Option<DownStreamInner>>>,
|
|
||||||
us_inner_m: Arc<Mutex<Option<UpStreamInner>>>,
|
|
||||||
inner_handlers: InnerHandlers<H>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static> FullDuplexTcp<H> {
|
|
||||||
|
|
||||||
pub fn new(ds_tcp_stream: DataStreamType, us_tcp_stream_type: TCPDataType, remote_host: String, remote_port: String, handlers: InnerHandlers<H>) -> Result<Self, i8> {
|
|
||||||
|
|
||||||
match ds_tcp_stream {
|
|
||||||
DataStreamType::RAW(ref s) => { let _ = s.set_read_timeout(Some(Duration::from_millis(50))); },
|
|
||||||
DataStreamType::TLS(ref s) => { let _ = s.get_ref().set_read_timeout(Some(Duration::from_millis(50))); },
|
|
||||||
}
|
|
||||||
|
|
||||||
let us_tcp_stream = match Self::connect_endpoint(us_tcp_stream_type, remote_host.clone(), remote_port.clone()) {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(ec) => {
|
|
||||||
match ds_tcp_stream {
|
|
||||||
DataStreamType::RAW(s) => { let _ = s.shutdown(Shutdown::Both); },
|
|
||||||
DataStreamType::TLS(mut s) => { let _ = s.shutdown(); },
|
|
||||||
}
|
|
||||||
return Err(ec);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(
|
|
||||||
FullDuplexTcp {
|
|
||||||
remote_host,
|
|
||||||
remote_port,
|
|
||||||
ds_inner_m: Arc::new(Mutex::new(Some(DownStreamInner{ds_stream: ds_tcp_stream, internal_data_buffer: Vec::<u8>::new()}))),
|
|
||||||
us_inner_m: Arc::new(Mutex::new(Some(UpStreamInner{us_stream: us_tcp_stream, internal_data_buffer: Vec::<u8>::new()}))),
|
|
||||||
inner_handlers: handlers,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle(&mut self) {
|
|
||||||
|
|
||||||
let (state_sender, state_receiver): (Sender<FullDuplexTcpState>, Receiver<FullDuplexTcpState>) = mpsc::channel();
|
|
||||||
let (ds_data_pipe_sender, ds_data_pipe_receiver): (Sender<DataPipe>, Receiver<DataPipe>) = mpsc::channel();
|
|
||||||
let (us_data_pipe_sender, us_data_pipe_receiver): (Sender<DataPipe>, Receiver<DataPipe>) = mpsc::channel();
|
|
||||||
|
|
||||||
let ds_method_pointer = self.ds_inner_m.clone();
|
|
||||||
let ds_state_bc = state_sender.clone();
|
|
||||||
|
|
||||||
let us_method_pointer = self.us_inner_m.clone();
|
|
||||||
let us_state_bc = state_sender.clone();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
ds_method_pointer.lock().unwrap().take().unwrap().ds_handler(ds_state_bc, ds_data_pipe_receiver);
|
|
||||||
});
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
us_method_pointer.lock().unwrap().take().unwrap().us_handler(us_state_bc, us_data_pipe_receiver);
|
|
||||||
});
|
|
||||||
|
|
||||||
loop {
|
|
||||||
|
|
||||||
match state_receiver.recv() {
|
|
||||||
Ok(state_request) => {
|
|
||||||
match state_request {
|
|
||||||
|
|
||||||
// DownStream Write Request
|
|
||||||
FullDuplexTcpState::DownStreamWrite(data) => {
|
|
||||||
|
|
||||||
/*
|
|
||||||
Callbacks that work with data from UpStream go here
|
|
||||||
Add callback return types for blocking callback subroutines
|
|
||||||
Shutdown - Shutdown TCP connection
|
|
||||||
Relay - Relay TCP stream
|
|
||||||
Spoof - Spoof back to received stream direction
|
|
||||||
Freeze - Freeze data (dont relay and destroy data)
|
|
||||||
*/
|
|
||||||
|
|
||||||
let inner_handlers_clone = self.inner_handlers.clone();
|
|
||||||
let in_data = data.clone();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
inner_handlers_clone.cb.us_nb_callback(in_data);
|
|
||||||
});
|
|
||||||
|
|
||||||
match self.inner_handlers.cb.us_b_callback(data) {
|
|
||||||
CallbackRet::Relay(retdata) => {
|
|
||||||
match ds_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
|
||||||
Ok(()) => {},
|
|
||||||
Err(e) => {
|
|
||||||
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CallbackRet::Spoof(retdata) => {
|
|
||||||
match us_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
|
||||||
Ok(()) => {},
|
|
||||||
Err(e) => {
|
|
||||||
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CallbackRet::Freeze => {},
|
|
||||||
CallbackRet::Shutdown => {
|
|
||||||
if let Err(e) = us_data_pipe_sender.send(DataPipe::Shutdown) {
|
|
||||||
Self::handle_error(format!("Failed to send Shutdown signal to UpStream thread: {}", e).as_str());
|
|
||||||
}
|
|
||||||
if let Err(e) = ds_data_pipe_sender.send(DataPipe::Shutdown) {
|
|
||||||
Self::handle_error(format!("Failed to send Shutdown signal to DownStream thread: {}", e).as_str());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
// UpStream Write Request
|
|
||||||
FullDuplexTcpState::UpStreamWrite(data) => {
|
|
||||||
|
|
||||||
/*
|
|
||||||
Callbacks that work with data from DownStream go here
|
|
||||||
*/
|
|
||||||
|
|
||||||
let inner_handlers_clone = self.inner_handlers.clone();
|
|
||||||
let in_data = data.clone();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
inner_handlers_clone.cb.ds_nb_callback(in_data);
|
|
||||||
});
|
|
||||||
|
|
||||||
match self.inner_handlers.cb.ds_b_callback(data) {
|
|
||||||
CallbackRet::Relay(retdata) => {
|
|
||||||
match us_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
|
||||||
Ok(()) => {},
|
|
||||||
Err(e) => {
|
|
||||||
Self::handle_error(format!("Failed to send data write to UpStream thread: {}", e).as_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CallbackRet::Spoof(retdata) => {
|
|
||||||
match ds_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
|
||||||
Ok(()) => {},
|
|
||||||
Err(e) => {
|
|
||||||
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CallbackRet::Freeze => {},
|
|
||||||
CallbackRet::Shutdown => {
|
|
||||||
if let Err(e) = ds_data_pipe_sender.send(DataPipe::Shutdown) {
|
|
||||||
Self::handle_error(format!("Failed to send Shutdown signal to DownStream thread: {}", e).as_str());
|
|
||||||
}
|
|
||||||
if let Err(e) = us_data_pipe_sender.send(DataPipe::Shutdown) {
|
|
||||||
Self::handle_error(format!("Failed to send Shutdown signal to UpStream thread: {}", e).as_str());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// DownStreamShutDown Request
|
|
||||||
FullDuplexTcpState::DownStreamShutDown => {
|
|
||||||
|
|
||||||
if let Err(e) = us_data_pipe_sender.send(DataPipe::Shutdown) {
|
|
||||||
Self::handle_error(format!("Failed to send Shutdown signal to UpStream thread: {}", e).as_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
// UpStreamShutDown Request
|
|
||||||
FullDuplexTcpState::UpStreamShutDown => {
|
|
||||||
|
|
||||||
if let Err(e) = ds_data_pipe_sender.send(DataPipe::Shutdown) {
|
|
||||||
Self::handle_error(format!("Failed to send Shutdown signal to DownStream thread: {}", e).as_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(_e) => {
|
|
||||||
Self::handle_error("State receiver communication channel has closed!");
|
|
||||||
if let Err(e) = ds_data_pipe_sender.send(DataPipe::Shutdown) {
|
|
||||||
Self::handle_error(format!("Failed to send Shutdown signal to DownStream thread: {}", e).as_str());
|
|
||||||
}
|
|
||||||
if let Err(e) = us_data_pipe_sender.send(DataPipe::Shutdown) {
|
|
||||||
Self::handle_error(format!("Failed to send Shutdown signal to UpStream thread: {}", e).as_str());
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}// State Receiver
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn connect_endpoint(stream_data_type: TCPDataType, remote_host: String, remote_port: String) -> Result<DataStreamType, i8> {
|
|
||||||
|
|
||||||
match stream_data_type {
|
|
||||||
|
|
||||||
TCPDataType::RAW => {
|
|
||||||
let s = match TcpStream::connect(format!("{}:{}", remote_host, remote_port)) {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(e) => {
|
|
||||||
Self::handle_error(format!("Can't connect to remote host: {}\nErr: {}", format!("{}:{}", remote_host, remote_port), e).as_str());
|
|
||||||
return Result::Err(-1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let _ = s.set_read_timeout(Some(Duration::from_millis(50)));
|
|
||||||
return Ok(DataStreamType::RAW(s));
|
|
||||||
|
|
||||||
},
|
|
||||||
TCPDataType::TLS => {
|
|
||||||
|
|
||||||
let mut sslbuilder = SslConnector::builder(SslMethod::tls()).unwrap();
|
|
||||||
sslbuilder.set_verify(SslVerifyMode::NONE);
|
|
||||||
|
|
||||||
let connector = sslbuilder.build();
|
|
||||||
|
|
||||||
let s = match TcpStream::connect(format!("{}:{}", remote_host, remote_port)) {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(e) => {
|
|
||||||
Self::handle_error(format!("Can't connect to remote host: {}\nErr: {}", format!("{}:{}", remote_host, remote_port), e).as_str());
|
|
||||||
return Result::Err(-1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let s = match connector.connect(remote_host.as_str(), s) {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(e) => {
|
|
||||||
Self::handle_error(format!("Failed to accept TLS/SSL handshake: {}", e).as_str());
|
|
||||||
return Result::Err(-2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let _ = s.get_ref().set_read_timeout(Some(Duration::from_millis(50)));
|
|
||||||
return Ok(DataStreamType::TLS(s));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_error(error_description: &str) {
|
|
||||||
println!("[SSLRelay Master Thread Error]: {}", error_description);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
293
src/lib.rs
293
src/lib.rs
|
|
@ -1,15 +1,71 @@
|
||||||
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
|
use openssl::ssl::{
|
||||||
use std::net::{TcpListener};
|
SslVerifyMode,
|
||||||
use std::sync::Arc;
|
SslConnector,
|
||||||
use std::{process, thread};
|
SslAcceptor,
|
||||||
use std::env;
|
SslStream,
|
||||||
use std::fs;
|
SslFiletype,
|
||||||
use std::path::Path;
|
SslMethod
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::net::{
|
||||||
|
TcpListener,
|
||||||
|
TcpStream,
|
||||||
|
Shutdown
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::sync::{
|
||||||
|
Arc,
|
||||||
|
Mutex
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
process,
|
||||||
|
thread
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
fs,
|
||||||
|
path::Path,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::io::{
|
||||||
|
self,
|
||||||
|
Read,
|
||||||
|
Write
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::sync::mpsc::{
|
||||||
|
self,
|
||||||
|
Receiver,
|
||||||
|
Sender
|
||||||
|
};
|
||||||
|
|
||||||
use toml::Value as TValue;
|
use toml::Value as TValue;
|
||||||
|
|
||||||
mod data;
|
mod data;
|
||||||
use data::{FullDuplexTcp, DataStreamType};
|
mod tcp;
|
||||||
|
mod relay;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum FullDuplexTcpState {
|
||||||
|
DownStreamWrite(Vec<u8>),
|
||||||
|
UpStreamWrite(Vec<u8>),
|
||||||
|
DownStreamShutDown,
|
||||||
|
UpStreamShutDown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum DataPipe {
|
||||||
|
DataWrite(Vec<u8>),
|
||||||
|
Shutdown,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DataStreamType {
|
||||||
|
RAW(TcpStream),
|
||||||
|
TLS(SslStream<TcpStream>),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum TCPDataType {
|
pub enum TCPDataType {
|
||||||
|
|
@ -17,6 +73,13 @@ pub enum TCPDataType {
|
||||||
RAW,
|
RAW,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ConfigType<T> {
|
||||||
|
Env,
|
||||||
|
Path(T),
|
||||||
|
Conf(RelayConfig),
|
||||||
|
Default,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RelayConfig {
|
pub struct RelayConfig {
|
||||||
pub downstream_data_type: TCPDataType,
|
pub downstream_data_type: TCPDataType,
|
||||||
|
|
@ -29,20 +92,6 @@ pub struct RelayConfig {
|
||||||
pub ssl_cert_path: String,
|
pub ssl_cert_path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HandlerCallbacks {
|
|
||||||
fn ds_b_callback(&self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
|
||||||
fn ds_nb_callback(&self, _in_data: Vec<u8>){}
|
|
||||||
fn us_b_callback(&self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
|
||||||
fn us_nb_callback(&self, _in_data: Vec<u8>){}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ConfigType<T> {
|
|
||||||
Env,
|
|
||||||
Path(T),
|
|
||||||
Conf(RelayConfig),
|
|
||||||
Default,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CallbackRet {
|
pub enum CallbackRet {
|
||||||
Relay(Vec<u8>),// Relay data
|
Relay(Vec<u8>),// Relay data
|
||||||
|
|
@ -51,6 +100,14 @@ pub enum CallbackRet {
|
||||||
Freeze,// Dont send data (pretend as if stream never was recieved)
|
Freeze,// Dont send data (pretend as if stream never was recieved)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait HandlerCallbacks {
|
||||||
|
fn ds_b_callback(&self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
||||||
|
fn ds_nb_callback(&self, _in_data: Vec<u8>){}
|
||||||
|
fn us_b_callback(&self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
||||||
|
fn us_nb_callback(&self, _in_data: Vec<u8>){}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SSLRelay<H>
|
pub struct SSLRelay<H>
|
||||||
where
|
where
|
||||||
|
|
@ -60,180 +117,34 @@ where
|
||||||
handlers: Option<InnerHandlers<H>>,
|
handlers: Option<InnerHandlers<H>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct FullDuplexTcp<H>
|
||||||
|
where
|
||||||
|
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static,
|
||||||
|
{
|
||||||
|
remote_host: String,
|
||||||
|
remote_port: String,
|
||||||
|
ds_inner_m: Arc<Mutex<Option<DownStreamInner>>>,
|
||||||
|
us_inner_m: Arc<Mutex<Option<UpStreamInner>>>,
|
||||||
|
inner_handlers: InnerHandlers<H>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct InnerHandlers<H>
|
struct InnerHandlers<H>
|
||||||
where
|
where
|
||||||
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static,
|
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static,
|
||||||
{
|
{
|
||||||
cb: H
|
cb: H
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static> SSLRelay<H> {
|
struct DownStreamInner
|
||||||
|
{
|
||||||
|
ds_stream: DataStreamType,
|
||||||
|
internal_data_buffer: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(handlers: H, config_path: ConfigType<String>) -> Self {
|
struct UpStreamInner
|
||||||
|
{
|
||||||
SSLRelay {
|
us_stream: DataStreamType,
|
||||||
config: Self::load_relay_config(config_path),
|
internal_data_buffer: Vec<u8>
|
||||||
handlers: Some(InnerHandlers{cb: handlers}),
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start(&mut self) {
|
|
||||||
|
|
||||||
let rhost = self.config.remote_host.clone();
|
|
||||||
let rport = self.config.remote_port.clone();
|
|
||||||
let listener = TcpListener::bind(format!("{}:{}", self.config.bind_host.clone(), self.config.bind_port.clone())).unwrap();
|
|
||||||
let upstream_data_stream_type = self.config.upstream_data_type;
|
|
||||||
|
|
||||||
match self.config.downstream_data_type {
|
|
||||||
|
|
||||||
TCPDataType::TLS => {
|
|
||||||
let acceptor = self.setup_ssl_config(self.config.ssl_private_key_path.clone(), self.config.ssl_cert_path.clone());
|
|
||||||
|
|
||||||
for stream in listener.incoming() {
|
|
||||||
|
|
||||||
match stream {
|
|
||||||
Ok(stream) => {
|
|
||||||
|
|
||||||
let acceptor = acceptor.clone();
|
|
||||||
let handler_clone = self.handlers.as_ref().unwrap().clone();
|
|
||||||
|
|
||||||
let r_host = rhost.clone();
|
|
||||||
let r_port = rport.clone();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
|
|
||||||
match acceptor.accept(stream) {
|
|
||||||
Ok(stream) => {
|
|
||||||
// FULL DUPLEX OBJECT CREATION HERE
|
|
||||||
match FullDuplexTcp::new(DataStreamType::TLS(stream), upstream_data_stream_type, r_host, r_port, handler_clone) {
|
|
||||||
Ok(mut fdtcp) => fdtcp.handle(),
|
|
||||||
Err(_ec) => {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
|
|
||||||
println!("[Error] {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
TCPDataType::RAW => {
|
|
||||||
|
|
||||||
for stream in listener.incoming() {
|
|
||||||
|
|
||||||
match stream {
|
|
||||||
Ok(stream) => {
|
|
||||||
|
|
||||||
let handler_clone = self.handlers.as_ref().unwrap().clone();
|
|
||||||
|
|
||||||
let r_host = rhost.clone();
|
|
||||||
let r_port = rport.clone();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
|
|
||||||
// FULL DUPLEX OBJECT CREATION HERE
|
|
||||||
match FullDuplexTcp::new(DataStreamType::RAW(stream), upstream_data_stream_type, r_host, r_port, handler_clone) {
|
|
||||||
Ok(mut fdtcp) => fdtcp.handle(),
|
|
||||||
Err(_ec) => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
},
|
|
||||||
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_relay_config(config_path: ConfigType<String>) -> RelayConfig {
|
|
||||||
|
|
||||||
let mut resolved_path = String::from("./relay_config.toml");
|
|
||||||
match config_path {
|
|
||||||
ConfigType::Path(path) => {
|
|
||||||
resolved_path = path.clone();
|
|
||||||
},
|
|
||||||
ConfigType::Env => {
|
|
||||||
resolved_path = match env::var("SSLRELAY_CONFIG") {
|
|
||||||
Ok(p) => p.clone(),
|
|
||||||
Err(_e) => {
|
|
||||||
println!("[-] Environmental variable SSLRELAY_CONFIG does not exist.");
|
|
||||||
std::process::exit(-1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
ConfigType::Conf(conf) => {
|
|
||||||
return conf;
|
|
||||||
}
|
|
||||||
ConfigType::Default => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let bytes = fs::read(resolved_path).unwrap();
|
|
||||||
let config_file = String::from_utf8_lossy(&bytes);
|
|
||||||
let config_parsed = config_file.parse::<TValue>().unwrap();
|
|
||||||
|
|
||||||
let bind_host = config_parsed["bind_host"].to_string().replace("\"", "");
|
|
||||||
let bind_port = config_parsed["bind_port"].to_string().replace("\"", "");
|
|
||||||
let ssl_private_key_path = config_parsed["ssl_private_key_path"].to_string().replace("\"", "");
|
|
||||||
let ssl_cert_path = config_parsed["ssl_cert_path"].to_string().replace("\"", "");
|
|
||||||
let remote_host = config_parsed["remote_host"].to_string().replace("\"", "");
|
|
||||||
let remote_port = config_parsed["remote_port"].to_string().replace("\"", "");
|
|
||||||
let upstream_tls_conf = config_parsed["upstream_data_type"].to_string().replace("\"", "").to_lowercase();
|
|
||||||
let downstream_tls_conf = config_parsed["downstream_data_type"].to_string().replace("\"", "").to_lowercase();
|
|
||||||
|
|
||||||
let upstream_data_type: TCPDataType;
|
|
||||||
let downstream_data_type: TCPDataType;
|
|
||||||
|
|
||||||
if upstream_tls_conf == "tls" {
|
|
||||||
upstream_data_type = TCPDataType::TLS;
|
|
||||||
} else if upstream_tls_conf == "raw" {
|
|
||||||
upstream_data_type = TCPDataType::RAW;
|
|
||||||
} else {
|
|
||||||
println!("[SSLRelay Error] Unrecognized TCPDataType for upstream_data_type. Data type received was not 'tcp' or 'tls'!");
|
|
||||||
process::exit(1); // Create error handling for load_relay_config()
|
|
||||||
}
|
|
||||||
|
|
||||||
if downstream_tls_conf == "tls" {
|
|
||||||
downstream_data_type = TCPDataType::TLS;
|
|
||||||
} else if downstream_tls_conf == "raw" {
|
|
||||||
downstream_data_type = TCPDataType::RAW;
|
|
||||||
} else {
|
|
||||||
println!("[SSLRelay Error] Unrecognized TCPDataType for downstream_data_type. Data type received was not 'tcp' or 'tls'!");
|
|
||||||
process::exit(1); // Create error handling for load_relay_config()
|
|
||||||
}
|
|
||||||
|
|
||||||
RelayConfig {
|
|
||||||
upstream_data_type,
|
|
||||||
downstream_data_type,
|
|
||||||
bind_host: bind_host.clone(),
|
|
||||||
bind_port: bind_port.clone(),
|
|
||||||
ssl_private_key_path: ssl_private_key_path.clone(),
|
|
||||||
ssl_cert_path: ssl_cert_path.clone(),
|
|
||||||
remote_host: remote_host.clone(),
|
|
||||||
remote_port: remote_port.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_ssl_config(&self, priv_key: String, cert: String) -> Arc<SslAcceptor> {
|
|
||||||
|
|
||||||
if !Path::new(priv_key.as_str()).exists() {
|
|
||||||
println!("[-] [{}] does not exist!", priv_key);
|
|
||||||
process::exit(-1);
|
|
||||||
} else if !Path::new(cert.as_str()).exists() {
|
|
||||||
println!("[-] [{}] does not exist!", cert);
|
|
||||||
process::exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
|
||||||
acceptor.set_private_key_file(priv_key, SslFiletype::PEM).unwrap();
|
|
||||||
acceptor.set_certificate_chain_file(cert).unwrap();
|
|
||||||
acceptor.check_private_key().unwrap();
|
|
||||||
Arc::new(acceptor.build())
|
|
||||||
}
|
|
||||||
}// SSLRelay
|
|
||||||
191
src/relay.rs
Normal file
191
src/relay.rs
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
use crate::{
|
||||||
|
SSLRelay,
|
||||||
|
HandlerCallbacks,
|
||||||
|
InnerHandlers,
|
||||||
|
TCPDataType,
|
||||||
|
ConfigType,
|
||||||
|
TcpListener,
|
||||||
|
thread,
|
||||||
|
FullDuplexTcp,
|
||||||
|
DataStreamType,
|
||||||
|
RelayConfig,
|
||||||
|
env,
|
||||||
|
TValue,
|
||||||
|
fs,
|
||||||
|
process,
|
||||||
|
Arc,
|
||||||
|
SslAcceptor,
|
||||||
|
Path,
|
||||||
|
SslMethod,
|
||||||
|
SslFiletype,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static> SSLRelay<H> {
|
||||||
|
|
||||||
|
pub fn new(handlers: H, config_path: ConfigType<String>) -> Self {
|
||||||
|
|
||||||
|
SSLRelay {
|
||||||
|
config: Self::load_relay_config(config_path),
|
||||||
|
handlers: Some(InnerHandlers{cb: handlers}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(&mut self) {
|
||||||
|
|
||||||
|
let rhost = self.config.remote_host.clone();
|
||||||
|
let rport = self.config.remote_port.clone();
|
||||||
|
let listener = TcpListener::bind(format!("{}:{}", self.config.bind_host.clone(), self.config.bind_port.clone())).unwrap();
|
||||||
|
let upstream_data_stream_type = self.config.upstream_data_type;
|
||||||
|
|
||||||
|
match self.config.downstream_data_type {
|
||||||
|
|
||||||
|
TCPDataType::TLS => {
|
||||||
|
let acceptor = self.setup_ssl_config(self.config.ssl_private_key_path.clone(), self.config.ssl_cert_path.clone());
|
||||||
|
|
||||||
|
for stream in listener.incoming() {
|
||||||
|
|
||||||
|
match stream {
|
||||||
|
Ok(stream) => {
|
||||||
|
|
||||||
|
let acceptor = acceptor.clone();
|
||||||
|
let handler_clone = self.handlers.as_ref().unwrap().clone();
|
||||||
|
|
||||||
|
let r_host = rhost.clone();
|
||||||
|
let r_port = rport.clone();
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
|
||||||
|
match acceptor.accept(stream) {
|
||||||
|
Ok(stream) => {
|
||||||
|
// FULL DUPLEX OBJECT CREATION HERE
|
||||||
|
match FullDuplexTcp::new(DataStreamType::TLS(stream), upstream_data_stream_type, r_host, r_port, handler_clone) {
|
||||||
|
Ok(mut fdtcp) => fdtcp.handle(),
|
||||||
|
Err(_ec) => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
|
||||||
|
println!("[Error] {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
TCPDataType::RAW => {
|
||||||
|
|
||||||
|
for stream in listener.incoming() {
|
||||||
|
|
||||||
|
match stream {
|
||||||
|
Ok(stream) => {
|
||||||
|
|
||||||
|
let handler_clone = self.handlers.as_ref().unwrap().clone();
|
||||||
|
|
||||||
|
let r_host = rhost.clone();
|
||||||
|
let r_port = rport.clone();
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
|
||||||
|
// FULL DUPLEX OBJECT CREATION HERE
|
||||||
|
match FullDuplexTcp::new(DataStreamType::RAW(stream), upstream_data_stream_type, r_host, r_port, handler_clone) {
|
||||||
|
Ok(mut fdtcp) => fdtcp.handle(),
|
||||||
|
Err(_ec) => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_relay_config(config_path: ConfigType<String>) -> RelayConfig {
|
||||||
|
|
||||||
|
let mut resolved_path = String::from("./relay_config.toml");
|
||||||
|
match config_path {
|
||||||
|
ConfigType::Path(path) => {
|
||||||
|
resolved_path = path.clone();
|
||||||
|
},
|
||||||
|
ConfigType::Env => {
|
||||||
|
resolved_path = match env::var("SSLRELAY_CONFIG") {
|
||||||
|
Ok(p) => p.clone(),
|
||||||
|
Err(_e) => {
|
||||||
|
println!("[-] Environmental variable SSLRELAY_CONFIG does not exist.");
|
||||||
|
std::process::exit(-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
ConfigType::Conf(conf) => {
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
ConfigType::Default => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let bytes = fs::read(resolved_path).unwrap();
|
||||||
|
let config_file = String::from_utf8_lossy(&bytes);
|
||||||
|
let config_parsed = config_file.parse::<TValue>().unwrap();
|
||||||
|
|
||||||
|
let bind_host = config_parsed["bind_host"].to_string().replace("\"", "");
|
||||||
|
let bind_port = config_parsed["bind_port"].to_string().replace("\"", "");
|
||||||
|
let ssl_private_key_path = config_parsed["ssl_private_key_path"].to_string().replace("\"", "");
|
||||||
|
let ssl_cert_path = config_parsed["ssl_cert_path"].to_string().replace("\"", "");
|
||||||
|
let remote_host = config_parsed["remote_host"].to_string().replace("\"", "");
|
||||||
|
let remote_port = config_parsed["remote_port"].to_string().replace("\"", "");
|
||||||
|
let upstream_tls_conf = config_parsed["upstream_data_type"].to_string().replace("\"", "").to_lowercase();
|
||||||
|
let downstream_tls_conf = config_parsed["downstream_data_type"].to_string().replace("\"", "").to_lowercase();
|
||||||
|
|
||||||
|
let upstream_data_type: TCPDataType;
|
||||||
|
let downstream_data_type: TCPDataType;
|
||||||
|
|
||||||
|
if upstream_tls_conf == "tls" {
|
||||||
|
upstream_data_type = TCPDataType::TLS;
|
||||||
|
} else if upstream_tls_conf == "raw" {
|
||||||
|
upstream_data_type = TCPDataType::RAW;
|
||||||
|
} else {
|
||||||
|
println!("[SSLRelay Error] Unrecognized TCPDataType for upstream_data_type. Data type received was not 'tcp' or 'tls'!");
|
||||||
|
process::exit(1); // Create error handling for load_relay_config()
|
||||||
|
}
|
||||||
|
|
||||||
|
if downstream_tls_conf == "tls" {
|
||||||
|
downstream_data_type = TCPDataType::TLS;
|
||||||
|
} else if downstream_tls_conf == "raw" {
|
||||||
|
downstream_data_type = TCPDataType::RAW;
|
||||||
|
} else {
|
||||||
|
println!("[SSLRelay Error] Unrecognized TCPDataType for downstream_data_type. Data type received was not 'tcp' or 'tls'!");
|
||||||
|
process::exit(1); // Create error handling for load_relay_config()
|
||||||
|
}
|
||||||
|
|
||||||
|
RelayConfig {
|
||||||
|
upstream_data_type,
|
||||||
|
downstream_data_type,
|
||||||
|
bind_host: bind_host.clone(),
|
||||||
|
bind_port: bind_port.clone(),
|
||||||
|
ssl_private_key_path: ssl_private_key_path.clone(),
|
||||||
|
ssl_cert_path: ssl_cert_path.clone(),
|
||||||
|
remote_host: remote_host.clone(),
|
||||||
|
remote_port: remote_port.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_ssl_config(&self, priv_key: String, cert: String) -> Arc<SslAcceptor> {
|
||||||
|
|
||||||
|
if !Path::new(priv_key.as_str()).exists() {
|
||||||
|
println!("[-] [{}] does not exist!", priv_key);
|
||||||
|
process::exit(-1);
|
||||||
|
} else if !Path::new(cert.as_str()).exists() {
|
||||||
|
println!("[-] [{}] does not exist!", cert);
|
||||||
|
process::exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
||||||
|
acceptor.set_private_key_file(priv_key, SslFiletype::PEM).unwrap();
|
||||||
|
acceptor.set_certificate_chain_file(cert).unwrap();
|
||||||
|
acceptor.check_private_key().unwrap();
|
||||||
|
Arc::new(acceptor.build())
|
||||||
|
}
|
||||||
|
}// SSLRelay
|
||||||
260
src/tcp.rs
Normal file
260
src/tcp.rs
Normal file
|
|
@ -0,0 +1,260 @@
|
||||||
|
use crate::{
|
||||||
|
FullDuplexTcp,
|
||||||
|
HandlerCallbacks,
|
||||||
|
DataStreamType,
|
||||||
|
TCPDataType,
|
||||||
|
Duration,
|
||||||
|
Arc,
|
||||||
|
Mutex,
|
||||||
|
DownStreamInner,
|
||||||
|
UpStreamInner,
|
||||||
|
InnerHandlers,
|
||||||
|
Shutdown,
|
||||||
|
Sender,
|
||||||
|
Receiver,
|
||||||
|
FullDuplexTcpState,
|
||||||
|
DataPipe,
|
||||||
|
mpsc,
|
||||||
|
thread,
|
||||||
|
CallbackRet,
|
||||||
|
TcpStream,
|
||||||
|
SslVerifyMode,
|
||||||
|
SslConnector,
|
||||||
|
SslMethod,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static> FullDuplexTcp<H> {
|
||||||
|
|
||||||
|
pub fn new(ds_tcp_stream: DataStreamType, us_tcp_stream_type: TCPDataType, remote_host: String, remote_port: String, handlers: InnerHandlers<H>) -> Result<Self, i8> {
|
||||||
|
|
||||||
|
match ds_tcp_stream {
|
||||||
|
DataStreamType::RAW(ref s) => { let _ = s.set_read_timeout(Some(Duration::from_millis(50))); },
|
||||||
|
DataStreamType::TLS(ref s) => { let _ = s.get_ref().set_read_timeout(Some(Duration::from_millis(50))); },
|
||||||
|
}
|
||||||
|
|
||||||
|
let us_tcp_stream = match Self::connect_endpoint(us_tcp_stream_type, remote_host.clone(), remote_port.clone()) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(ec) => {
|
||||||
|
match ds_tcp_stream {
|
||||||
|
DataStreamType::RAW(s) => { let _ = s.shutdown(Shutdown::Both); },
|
||||||
|
DataStreamType::TLS(mut s) => { let _ = s.shutdown(); },
|
||||||
|
}
|
||||||
|
return Err(ec);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(
|
||||||
|
FullDuplexTcp {
|
||||||
|
remote_host,
|
||||||
|
remote_port,
|
||||||
|
ds_inner_m: Arc::new(Mutex::new(Some(DownStreamInner{ds_stream: ds_tcp_stream, internal_data_buffer: Vec::<u8>::new()}))),
|
||||||
|
us_inner_m: Arc::new(Mutex::new(Some(UpStreamInner{us_stream: us_tcp_stream, internal_data_buffer: Vec::<u8>::new()}))),
|
||||||
|
inner_handlers: handlers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle(&mut self) {
|
||||||
|
|
||||||
|
let (state_sender, state_receiver): (Sender<FullDuplexTcpState>, Receiver<FullDuplexTcpState>) = mpsc::channel();
|
||||||
|
let (ds_data_pipe_sender, ds_data_pipe_receiver): (Sender<DataPipe>, Receiver<DataPipe>) = mpsc::channel();
|
||||||
|
let (us_data_pipe_sender, us_data_pipe_receiver): (Sender<DataPipe>, Receiver<DataPipe>) = mpsc::channel();
|
||||||
|
|
||||||
|
let ds_method_pointer = self.ds_inner_m.clone();
|
||||||
|
let ds_state_bc = state_sender.clone();
|
||||||
|
|
||||||
|
let us_method_pointer = self.us_inner_m.clone();
|
||||||
|
let us_state_bc = state_sender.clone();
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
ds_method_pointer.lock().unwrap().take().unwrap().ds_handler(ds_state_bc, ds_data_pipe_receiver);
|
||||||
|
});
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
us_method_pointer.lock().unwrap().take().unwrap().us_handler(us_state_bc, us_data_pipe_receiver);
|
||||||
|
});
|
||||||
|
|
||||||
|
loop {
|
||||||
|
|
||||||
|
match state_receiver.recv() {
|
||||||
|
Ok(state_request) => {
|
||||||
|
match state_request {
|
||||||
|
|
||||||
|
// DownStream Write Request
|
||||||
|
FullDuplexTcpState::DownStreamWrite(data) => {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Callbacks that work with data from UpStream go here
|
||||||
|
Add callback return types for blocking callback subroutines
|
||||||
|
Shutdown - Shutdown TCP connection
|
||||||
|
Relay - Relay TCP stream
|
||||||
|
Spoof - Spoof back to received stream direction
|
||||||
|
Freeze - Freeze data (dont relay and destroy data)
|
||||||
|
*/
|
||||||
|
|
||||||
|
let inner_handlers_clone = self.inner_handlers.clone();
|
||||||
|
let in_data = data.clone();
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
inner_handlers_clone.cb.us_nb_callback(in_data);
|
||||||
|
});
|
||||||
|
|
||||||
|
match self.inner_handlers.cb.us_b_callback(data) {
|
||||||
|
CallbackRet::Relay(retdata) => {
|
||||||
|
match ds_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
||||||
|
Ok(()) => {},
|
||||||
|
Err(e) => {
|
||||||
|
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CallbackRet::Spoof(retdata) => {
|
||||||
|
match us_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
||||||
|
Ok(()) => {},
|
||||||
|
Err(e) => {
|
||||||
|
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CallbackRet::Freeze => {},
|
||||||
|
CallbackRet::Shutdown => {
|
||||||
|
if let Err(e) = us_data_pipe_sender.send(DataPipe::Shutdown) {
|
||||||
|
Self::handle_error(format!("Failed to send Shutdown signal to UpStream thread: {}", e).as_str());
|
||||||
|
}
|
||||||
|
if let Err(e) = ds_data_pipe_sender.send(DataPipe::Shutdown) {
|
||||||
|
Self::handle_error(format!("Failed to send Shutdown signal to DownStream thread: {}", e).as_str());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
// UpStream Write Request
|
||||||
|
FullDuplexTcpState::UpStreamWrite(data) => {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Callbacks that work with data from DownStream go here
|
||||||
|
*/
|
||||||
|
|
||||||
|
let inner_handlers_clone = self.inner_handlers.clone();
|
||||||
|
let in_data = data.clone();
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
inner_handlers_clone.cb.ds_nb_callback(in_data);
|
||||||
|
});
|
||||||
|
|
||||||
|
match self.inner_handlers.cb.ds_b_callback(data) {
|
||||||
|
CallbackRet::Relay(retdata) => {
|
||||||
|
match us_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
||||||
|
Ok(()) => {},
|
||||||
|
Err(e) => {
|
||||||
|
Self::handle_error(format!("Failed to send data write to UpStream thread: {}", e).as_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CallbackRet::Spoof(retdata) => {
|
||||||
|
match ds_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
||||||
|
Ok(()) => {},
|
||||||
|
Err(e) => {
|
||||||
|
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CallbackRet::Freeze => {},
|
||||||
|
CallbackRet::Shutdown => {
|
||||||
|
if let Err(e) = ds_data_pipe_sender.send(DataPipe::Shutdown) {
|
||||||
|
Self::handle_error(format!("Failed to send Shutdown signal to DownStream thread: {}", e).as_str());
|
||||||
|
}
|
||||||
|
if let Err(e) = us_data_pipe_sender.send(DataPipe::Shutdown) {
|
||||||
|
Self::handle_error(format!("Failed to send Shutdown signal to UpStream thread: {}", e).as_str());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// DownStreamShutDown Request
|
||||||
|
FullDuplexTcpState::DownStreamShutDown => {
|
||||||
|
|
||||||
|
if let Err(e) = us_data_pipe_sender.send(DataPipe::Shutdown) {
|
||||||
|
Self::handle_error(format!("Failed to send Shutdown signal to UpStream thread: {}", e).as_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
// UpStreamShutDown Request
|
||||||
|
FullDuplexTcpState::UpStreamShutDown => {
|
||||||
|
|
||||||
|
if let Err(e) = ds_data_pipe_sender.send(DataPipe::Shutdown) {
|
||||||
|
Self::handle_error(format!("Failed to send Shutdown signal to DownStream thread: {}", e).as_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_e) => {
|
||||||
|
Self::handle_error("State receiver communication channel has closed!");
|
||||||
|
if let Err(e) = ds_data_pipe_sender.send(DataPipe::Shutdown) {
|
||||||
|
Self::handle_error(format!("Failed to send Shutdown signal to DownStream thread: {}", e).as_str());
|
||||||
|
}
|
||||||
|
if let Err(e) = us_data_pipe_sender.send(DataPipe::Shutdown) {
|
||||||
|
Self::handle_error(format!("Failed to send Shutdown signal to UpStream thread: {}", e).as_str());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}// State Receiver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect_endpoint(stream_data_type: TCPDataType, remote_host: String, remote_port: String) -> Result<DataStreamType, i8> {
|
||||||
|
|
||||||
|
match stream_data_type {
|
||||||
|
|
||||||
|
TCPDataType::RAW => {
|
||||||
|
let s = match TcpStream::connect(format!("{}:{}", remote_host, remote_port)) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => {
|
||||||
|
Self::handle_error(format!("Can't connect to remote host: {}\nErr: {}", format!("{}:{}", remote_host, remote_port), e).as_str());
|
||||||
|
return Result::Err(-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _ = s.set_read_timeout(Some(Duration::from_millis(50)));
|
||||||
|
return Ok(DataStreamType::RAW(s));
|
||||||
|
|
||||||
|
},
|
||||||
|
TCPDataType::TLS => {
|
||||||
|
|
||||||
|
let mut sslbuilder = SslConnector::builder(SslMethod::tls()).unwrap();
|
||||||
|
sslbuilder.set_verify(SslVerifyMode::NONE);
|
||||||
|
|
||||||
|
let connector = sslbuilder.build();
|
||||||
|
|
||||||
|
let s = match TcpStream::connect(format!("{}:{}", remote_host, remote_port)) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => {
|
||||||
|
Self::handle_error(format!("Can't connect to remote host: {}\nErr: {}", format!("{}:{}", remote_host, remote_port), e).as_str());
|
||||||
|
return Result::Err(-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let s = match connector.connect(remote_host.as_str(), s) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => {
|
||||||
|
Self::handle_error(format!("Failed to accept TLS/SSL handshake: {}", e).as_str());
|
||||||
|
return Result::Err(-2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = s.get_ref().set_read_timeout(Some(Duration::from_millis(50)));
|
||||||
|
return Ok(DataStreamType::TLS(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_error(error_description: &str) {
|
||||||
|
println!("[SSLRelay Master Thread Error]: {}", error_description);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue