Fmt, add experimental features
This commit is contained in:
parent
0e9b4feaf7
commit
6828beeb52
8 changed files with 1091 additions and 963 deletions
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"rust-analyzer.showUnlinkedFileNotification": false
|
||||
}
|
||||
66
examples/basic.rs
Normal file
66
examples/basic.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
use sslrelay::{self, CallbackRet, HandlerCallbacks, RelayConfig, TCPDataType, TLSConfig};
|
||||
|
||||
// Handler object
|
||||
#[derive(Clone)] // Must have Clone trait implemented.
|
||||
struct Handler;
|
||||
|
||||
/*
|
||||
Callback traits that can be used to read or inject data
|
||||
into data upstream or downstream.
|
||||
*/
|
||||
impl HandlerCallbacks for Handler {
|
||||
// DownStream non blocking callback
|
||||
fn ds_nb_callback(&self, in_data: Vec<u8>, _conn_id: u64) {
|
||||
if let Ok(in_data) = str::from_utf8(&in_data) {
|
||||
println!("[downstream] {in_data}");
|
||||
} else {
|
||||
//println!("[downstream] {in_data:?}");
|
||||
}
|
||||
}
|
||||
|
||||
// DownStream blocking callback
|
||||
fn ds_b_callback(&mut self, _in_data: Vec<u8>, _conn_id: u64) -> CallbackRet {
|
||||
//println!("[CALLBACK] Down Stream Blocking CallBack!");
|
||||
CallbackRet::Relay(_in_data)
|
||||
}
|
||||
|
||||
// UpStream non blocking callback
|
||||
fn us_nb_callback(&self, in_data: Vec<u8>, _conn_id: u64) {
|
||||
if let Ok(in_data) = str::from_utf8(&in_data) {
|
||||
println!("[upstream] {in_data}");
|
||||
} else {
|
||||
//println!("[upstream] {in_data:?}");
|
||||
}
|
||||
}
|
||||
|
||||
// UpStream blocking callback
|
||||
fn us_b_callback(&mut self, _in_data: Vec<u8>, _conn_id: u64) -> CallbackRet {
|
||||
//println!("[CALLBACK] Up Stream Blocking CallBack!");
|
||||
CallbackRet::Relay(_in_data)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Create new SSLRelay object
|
||||
let mut relay = sslrelay::SSLRelay::new(
|
||||
Handler,
|
||||
RelayConfig {
|
||||
downstream_data_type: TCPDataType::TLS,
|
||||
upstream_data_type: TCPDataType::TLS,
|
||||
bind_host: "127.0.0.1".to_string(),
|
||||
bind_port: "443".to_string(),
|
||||
remote_host: |server_name| {
|
||||
server_name.map_or_else(|| panic!("NO HOST"), str::to_string)
|
||||
},
|
||||
remote_port: "443".to_string(),
|
||||
tls_config:
|
||||
TLSConfig::FILE {
|
||||
certificate_path: "/dev/shm/exp/certs/prime256v1/apple.com.crt".to_string(),
|
||||
private_key_path: "/dev/shm/exp/certs/prime256v1/apple.com.key".to_string(),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// Start listening
|
||||
relay.start();
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
use sslrelay::{self, RelayConfig, HandlerCallbacks, CallbackRet, TCPDataType, TLSConfig};
|
||||
|
||||
// Handler object
|
||||
#[derive(Clone)] // Must have Clone trait implemented.
|
||||
struct Handler;
|
||||
|
||||
/*
|
||||
Callback traits that can be used to read or inject data
|
||||
into data upstream or downstream.
|
||||
*/
|
||||
impl HandlerCallbacks for Handler {
|
||||
|
||||
// DownStream non blocking callback
|
||||
fn ds_nb_callback(&self, _in_data: Vec<u8>) {
|
||||
println!("[CALLBACK] Down Stream Non Blocking CallBack!");
|
||||
}
|
||||
|
||||
// DownStream blocking callback
|
||||
fn ds_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {
|
||||
println!("[CALLBACK] Down Stream Blocking CallBack!");
|
||||
CallbackRet::Relay(_in_data)
|
||||
}
|
||||
|
||||
// UpStream non blocking callback
|
||||
fn us_nb_callback(&self, _in_data: Vec<u8>) {
|
||||
println!("[CALLBACK] Up Stream Non Blocking CallBack!");
|
||||
}
|
||||
|
||||
// UpStream blocking callback
|
||||
fn us_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {
|
||||
println!("[CALLBACK] Up Stream Blocking CallBack!");
|
||||
CallbackRet::Relay(_in_data)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
// Create new SSLRelay object
|
||||
let mut relay = sslrelay::SSLRelay::new(
|
||||
Handler,
|
||||
RelayConfig {
|
||||
downstream_data_type: TCPDataType::TLS,
|
||||
upstream_data_type: TCPDataType::TLS,
|
||||
bind_host: "0.0.0.0".to_string(),
|
||||
bind_port: "443".to_string(),
|
||||
remote_host: "remote.com".to_string(),
|
||||
remote_port: "443".to_string(),
|
||||
tls_config: TLSConfig::FILE{
|
||||
certificate_path: "./tls.crt".to_string(),
|
||||
private_key_path: "./tls.key".to_string(),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Start listening
|
||||
relay.start();
|
||||
}
|
||||
8
rustfmt.toml
Normal file
8
rustfmt.toml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
hard_tabs = true
|
||||
newline_style = "unix"
|
||||
|
||||
unstable_features = true
|
||||
format_code_in_doc_comments = true
|
||||
format_macro_bodies = true
|
||||
format_macro_matchers = true
|
||||
format_strings = true
|
||||
227
src/data.rs
227
src/data.rs
|
|
@ -1,27 +1,14 @@
|
|||
use crate::{
|
||||
DownStreamInner,
|
||||
UpStreamInner,
|
||||
FullDuplexTcpState,
|
||||
DataPipe,
|
||||
DataStreamType,
|
||||
Sender,
|
||||
Receiver,
|
||||
Shutdown,
|
||||
mpsc,
|
||||
Duration,
|
||||
Read,
|
||||
Write,
|
||||
io,
|
||||
io, mpsc, DataPipe, DataStreamType, DownStreamInner, Duration, FullDuplexTcpState, Read,
|
||||
Receiver, Sender, Shutdown, UpStreamInner, Write,
|
||||
};
|
||||
|
||||
impl DownStreamInner {
|
||||
|
||||
fn handle_error(error_description: &str) {
|
||||
println!("[SSLRelay DownStream Thread Error]: {}", error_description);
|
||||
}
|
||||
|
||||
pub fn ds_handler(self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
||||
|
||||
match &self.ds_stream {
|
||||
DataStreamType::RAW(_) => self.handle_raw(data_out, data_in),
|
||||
DataStreamType::TLS(_) => self.handle_tls(data_out, data_in),
|
||||
|
|
@ -29,200 +16,172 @@ impl DownStreamInner {
|
|||
}
|
||||
|
||||
fn handle_raw(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
||||
|
||||
let mut raw_stream = match &self.ds_stream {
|
||||
DataStreamType::RAW(ref s) => s,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
loop {
|
||||
|
||||
match data_in.recv_timeout(Duration::from_millis(50)) {
|
||||
|
||||
// DataPipe Received
|
||||
Ok(data_received) => {
|
||||
|
||||
match data_received {
|
||||
Ok(data_received) => match data_received {
|
||||
DataPipe::DataWrite(data) => {
|
||||
|
||||
match raw_stream.write_all(&data) {
|
||||
Ok(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(_e) => {
|
||||
Self::handle_error("Failed to write data to DownStream tcp stream!");
|
||||
Self::handle_error(
|
||||
"Failed to write data to DownStream tcp stream!",
|
||||
);
|
||||
let _ = data_out.send(FullDuplexTcpState::DownStreamShutDown);
|
||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||
return;
|
||||
}
|
||||
}
|
||||
let _ = raw_stream.flush();
|
||||
|
||||
},
|
||||
}
|
||||
DataPipe::Shutdown => {
|
||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||
return;
|
||||
},
|
||||
}
|
||||
},
|
||||
Err(_e) => {
|
||||
match _e {
|
||||
mpsc::RecvTimeoutError::Timeout => {},
|
||||
Err(_e) => match _e {
|
||||
mpsc::RecvTimeoutError::Timeout => {}
|
||||
mpsc::RecvTimeoutError::Disconnected => {
|
||||
Self::handle_error("DownStream data_in channel is disconnected!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}// End of data_in receive
|
||||
},
|
||||
} // End of data_in receive
|
||||
|
||||
// If received data
|
||||
if let Some(byte_count) = Self::get_data_stream(&mut raw_stream, &mut self.internal_data_buffer) {
|
||||
if let Some(byte_count) =
|
||||
Self::get_data_stream(&mut raw_stream, &mut self.internal_data_buffer)
|
||||
{
|
||||
if byte_count > 0 {
|
||||
|
||||
if let Err(_e) = data_out.send(FullDuplexTcpState::UpStreamWrite(self.internal_data_buffer.clone())) {
|
||||
|
||||
if let Err(_e) = data_out.send(FullDuplexTcpState::UpStreamWrite(
|
||||
self.internal_data_buffer.clone(),
|
||||
)) {
|
||||
//Self::handle_error(format!("Failed to send UpStreamWrite to main thread: {}", e).as_str());
|
||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||
return;
|
||||
}
|
||||
|
||||
self.internal_data_buffer.clear();
|
||||
|
||||
} else if byte_count == 0 || byte_count == -2 {
|
||||
|
||||
let _ = data_out.send(FullDuplexTcpState::DownStreamShutDown);
|
||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||
return;
|
||||
|
||||
} else if byte_count == -1 {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_tls(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
||||
|
||||
let mut tls_stream = match self.ds_stream {
|
||||
DataStreamType::TLS(ref mut s) => s,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
loop {
|
||||
|
||||
match data_in.recv_timeout(Duration::from_millis(50)) {
|
||||
|
||||
// DataPipe Received
|
||||
Ok(data_received) => {
|
||||
|
||||
match data_received {
|
||||
Ok(data_received) => match data_received {
|
||||
DataPipe::DataWrite(data) => {
|
||||
|
||||
match tls_stream.write_all(&data) {
|
||||
Ok(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(_e) => {
|
||||
Self::handle_error("Failed to write data to DownStream tcp stream!");
|
||||
Self::handle_error(
|
||||
"Failed to write data to DownStream tcp stream!",
|
||||
);
|
||||
let _ = data_out.send(FullDuplexTcpState::DownStreamShutDown);
|
||||
let _ = tls_stream.shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
let _ = tls_stream.flush();
|
||||
},
|
||||
}
|
||||
DataPipe::Shutdown => {
|
||||
let _ = tls_stream.shutdown();
|
||||
return;
|
||||
},
|
||||
}
|
||||
},
|
||||
Err(_e) => {
|
||||
match _e {
|
||||
mpsc::RecvTimeoutError::Timeout => {},
|
||||
Err(_e) => match _e {
|
||||
mpsc::RecvTimeoutError::Timeout => {}
|
||||
mpsc::RecvTimeoutError::Disconnected => {
|
||||
Self::handle_error("DownStream data_in channel is disconnected!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}// End of data_in receive
|
||||
},
|
||||
} // End of data_in receive
|
||||
|
||||
// If received data
|
||||
if let Some(byte_count) = Self::get_data_stream(&mut tls_stream, &mut self.internal_data_buffer) {
|
||||
if let Some(byte_count) =
|
||||
Self::get_data_stream(&mut tls_stream, &mut self.internal_data_buffer)
|
||||
{
|
||||
if byte_count > 0 {
|
||||
|
||||
if let Err(_e) = data_out.send(FullDuplexTcpState::UpStreamWrite(self.internal_data_buffer.clone())) {
|
||||
|
||||
if let Err(_e) = data_out.send(FullDuplexTcpState::UpStreamWrite(
|
||||
self.internal_data_buffer.clone(),
|
||||
)) {
|
||||
//Self::handle_error(format!("Failed to send UpStreamWrite to main thread: {}", e).as_str());
|
||||
let _ = tls_stream.shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
self.internal_data_buffer.clear();
|
||||
|
||||
} else if byte_count == 0 || byte_count == -2 {
|
||||
|
||||
let _ = data_out.send(FullDuplexTcpState::DownStreamShutDown);
|
||||
let _ = tls_stream.shutdown();
|
||||
return;
|
||||
|
||||
} else if byte_count == -1 {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_data_stream<S: Read>(stream: &mut S, internal_data_buffer: &mut Vec<u8>) -> Option<i64> {
|
||||
|
||||
let mut data_length: i64 = 0;
|
||||
|
||||
loop {
|
||||
|
||||
let mut r_buf = [0; 1024];
|
||||
|
||||
match stream.read(&mut r_buf) {
|
||||
|
||||
Ok(bytes_read) => {
|
||||
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
|
||||
} else if bytes_read != 0 && bytes_read <= 1024 {
|
||||
|
||||
/*
|
||||
let mut tmp_buf = r_buf.to_vec();
|
||||
tmp_buf.truncate(bytes_read);
|
||||
*/
|
||||
|
||||
|
||||
//let _bw = self.internal_data_buffer.write(&tmp_buf).unwrap();
|
||||
|
||||
let _bw = internal_data_buffer.write(r_buf.split_at(bytes_read).0).unwrap();
|
||||
let _bw = internal_data_buffer
|
||||
.write(r_buf.split_at(bytes_read).0)
|
||||
.unwrap();
|
||||
data_length += bytes_read as i64;
|
||||
|
||||
} else {
|
||||
println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
match e.kind() {
|
||||
|
||||
}
|
||||
Err(e) => match e.kind() {
|
||||
io::ErrorKind::WouldBlock => {
|
||||
if data_length == 0 {
|
||||
|
||||
data_length = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
},
|
||||
}
|
||||
io::ErrorKind::ConnectionReset => {
|
||||
data_length = -2;
|
||||
break;
|
||||
},
|
||||
_ => {println!("[!!!] Got error: {}",e);}
|
||||
}
|
||||
_ => {
|
||||
println!("[!!!downstream] Got error: {}", e);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -231,40 +190,30 @@ impl DownStreamInner {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl UpStreamInner {
|
||||
|
||||
fn handle_error(error_description: &str) {
|
||||
println!("[SSLRelay UpStream Thread Error]: {}", error_description);
|
||||
}
|
||||
|
||||
pub fn us_handler(self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
||||
|
||||
match &self.us_stream {
|
||||
DataStreamType::RAW(_) => self.handle_raw(data_out, data_in),
|
||||
DataStreamType::TLS(_) => self.handle_tls(data_out, data_in),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn handle_raw(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
||||
|
||||
let mut raw_stream = match self.us_stream {
|
||||
DataStreamType::RAW(ref s) => s,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
loop {
|
||||
|
||||
match data_in.recv_timeout(Duration::from_millis(50)) {
|
||||
|
||||
Ok(data_received) => {
|
||||
|
||||
match data_received {
|
||||
Ok(data_received) => match data_received {
|
||||
DataPipe::DataWrite(data) => {
|
||||
|
||||
match raw_stream.write_all(&data) {
|
||||
Ok(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(_e) => {
|
||||
Self::handle_error("Failed to write data to UpStream tcp stream!");
|
||||
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
||||
|
|
@ -273,38 +222,35 @@ impl UpStreamInner {
|
|||
}
|
||||
}
|
||||
let _ = raw_stream.flush();
|
||||
},
|
||||
}
|
||||
DataPipe::Shutdown => {
|
||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
match e {
|
||||
mpsc::RecvTimeoutError::Timeout => {},
|
||||
Err(e) => match e {
|
||||
mpsc::RecvTimeoutError::Timeout => {}
|
||||
mpsc::RecvTimeoutError::Disconnected => {
|
||||
Self::handle_error("UpStream data_in channel is disconnected!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}// End of data_in receive
|
||||
},
|
||||
} // End of data_in receive
|
||||
|
||||
if let Some(byte_count) = Self::get_data_stream(&mut raw_stream, &mut self.internal_data_buffer) {
|
||||
if let Some(byte_count) =
|
||||
Self::get_data_stream(&mut raw_stream, &mut self.internal_data_buffer)
|
||||
{
|
||||
if byte_count > 0 {
|
||||
|
||||
if let Err(_e) = data_out.send(FullDuplexTcpState::DownStreamWrite(self.internal_data_buffer.clone())) {
|
||||
|
||||
if let Err(_e) = data_out.send(FullDuplexTcpState::DownStreamWrite(
|
||||
self.internal_data_buffer.clone(),
|
||||
)) {
|
||||
//Self::handle_error(format!("Failed to send DownStreamWrite to main thread: {}", e).as_str());
|
||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||
return;
|
||||
}
|
||||
|
||||
self.internal_data_buffer.clear();
|
||||
|
||||
} else if byte_count == 0 || byte_count == -2 {
|
||||
|
||||
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||
return;
|
||||
|
|
@ -317,23 +263,17 @@ impl UpStreamInner {
|
|||
}
|
||||
|
||||
fn handle_tls(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
||||
|
||||
let mut tls_stream = match self.us_stream {
|
||||
DataStreamType::TLS(ref mut s) => s,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
loop {
|
||||
|
||||
match data_in.recv_timeout(Duration::from_millis(50)) {
|
||||
|
||||
Ok(data_received) => {
|
||||
|
||||
match data_received {
|
||||
Ok(data_received) => match data_received {
|
||||
DataPipe::DataWrite(data) => {
|
||||
|
||||
match tls_stream.write_all(&data) {
|
||||
Ok(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(_e) => {
|
||||
Self::handle_error("Failed to write data to UpStream tcp stream!");
|
||||
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
||||
|
|
@ -342,38 +282,35 @@ impl UpStreamInner {
|
|||
}
|
||||
}
|
||||
let _ = tls_stream.flush();
|
||||
},
|
||||
}
|
||||
DataPipe::Shutdown => {
|
||||
let _ = tls_stream.shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
match e {
|
||||
mpsc::RecvTimeoutError::Timeout => {},
|
||||
Err(e) => match e {
|
||||
mpsc::RecvTimeoutError::Timeout => {}
|
||||
mpsc::RecvTimeoutError::Disconnected => {
|
||||
Self::handle_error("UpStream data_in channel is disconnected!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}// End of data_in receive
|
||||
},
|
||||
} // End of data_in receive
|
||||
|
||||
if let Some(byte_count) = Self::get_data_stream(&mut tls_stream, &mut self.internal_data_buffer) {
|
||||
if let Some(byte_count) =
|
||||
Self::get_data_stream(&mut tls_stream, &mut self.internal_data_buffer)
|
||||
{
|
||||
if byte_count > 0 {
|
||||
|
||||
if let Err(_e) = data_out.send(FullDuplexTcpState::DownStreamWrite(self.internal_data_buffer.clone())) {
|
||||
|
||||
if let Err(_e) = data_out.send(FullDuplexTcpState::DownStreamWrite(
|
||||
self.internal_data_buffer.clone(),
|
||||
)) {
|
||||
//Self::handle_error(format!("Failed to send DownStreamWrite to main thread: {}", e).as_str());
|
||||
let _ = tls_stream.shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
self.internal_data_buffer.clear();
|
||||
|
||||
} else if byte_count == 0 || byte_count == -2 {
|
||||
|
||||
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
||||
let _ = tls_stream.shutdown();
|
||||
return;
|
||||
|
|
@ -386,52 +323,44 @@ impl UpStreamInner {
|
|||
}
|
||||
|
||||
fn get_data_stream<S: Read>(stream: &mut S, internal_data_buffer: &mut Vec<u8>) -> Option<i64> {
|
||||
|
||||
let mut data_length: i64 = 0;
|
||||
|
||||
loop {
|
||||
|
||||
let mut r_buf = [0; 1024];
|
||||
|
||||
match stream.read(&mut r_buf) {
|
||||
|
||||
Ok(bytes_read) => {
|
||||
|
||||
if bytes_read == 0 {
|
||||
|
||||
break;
|
||||
|
||||
} else if bytes_read != 0 && bytes_read <= 1024 {
|
||||
|
||||
/*
|
||||
let mut tmp_buf = r_buf.to_vec();
|
||||
tmp_buf.truncate(bytes_read);
|
||||
*/
|
||||
|
||||
|
||||
//let _bw = self.internal_data_buffer.write(&tmp_buf).unwrap();
|
||||
|
||||
let _bw = internal_data_buffer.write(r_buf.split_at(bytes_read).0).unwrap();
|
||||
let _bw = internal_data_buffer
|
||||
.write(r_buf.split_at(bytes_read).0)
|
||||
.unwrap();
|
||||
data_length += bytes_read as i64;
|
||||
|
||||
} else {
|
||||
println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
match e.kind() {
|
||||
|
||||
}
|
||||
Err(e) => match e.kind() {
|
||||
io::ErrorKind::WouldBlock => {
|
||||
if data_length == 0 {
|
||||
data_length = -1;
|
||||
}
|
||||
break;
|
||||
},
|
||||
}
|
||||
io::ErrorKind::ConnectionReset => {
|
||||
data_length = -2;
|
||||
break;
|
||||
},
|
||||
_ => {println!("[!!!] Got error: {}",e);}
|
||||
}
|
||||
_ => {
|
||||
println!("[!!!upstream] Got error: {}", e);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
|||
126
src/lib.rs
126
src/lib.rs
|
|
@ -4,26 +4,30 @@
|
|||
//! This library allows you to implement callback functions for upstream and downstream traffic.
|
||||
//! These callbacks can R/W the data from a stream(Blocking) or only R the data(Non-Blocking).
|
||||
//!```
|
||||
//!pub trait HandlerCallbacks {
|
||||
//! fn ds_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
||||
//! fn ds_nb_callback(&self, _in_data: Vec<u8>){}
|
||||
//! fn us_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
||||
//! fn us_nb_callback(&self, _in_data: Vec<u8>){}
|
||||
//!}
|
||||
//!```
|
||||
//! pub trait HandlerCallbacks {
|
||||
//! fn ds_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {
|
||||
//! CallbackRet::Relay(_in_data)
|
||||
//! }
|
||||
//! fn ds_nb_callback(&self, _in_data: Vec<u8>) {}
|
||||
//! fn us_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {
|
||||
//! CallbackRet::Relay(_in_data)
|
||||
//! }
|
||||
//! fn us_nb_callback(&self, _in_data: Vec<u8>) {}
|
||||
//! }
|
||||
//! ```
|
||||
//! The blocking callbacks return an enum called CallbackRet with four different variants.
|
||||
//! The variants control the flow of the tcp stream.
|
||||
//!```
|
||||
//! pub enum CallbackRet {
|
||||
//! Relay(Vec<u8>),// Relay data
|
||||
//! Spoof(Vec<u8>),// Skip relaying and send data back
|
||||
//! Shutdown,// Shutdown TCP connection
|
||||
//! Freeze,// Dont send data (pretend as if stream never was recieved)
|
||||
//! Relay(Vec<u8>), // Relay data
|
||||
//! Spoof(Vec<u8>), // Skip relaying and send data back
|
||||
//! Shutdown, // Shutdown TCP connection
|
||||
//! Freeze, // Dont send data (pretend as if stream never was recieved)
|
||||
//! }
|
||||
//! ```
|
||||
//! ## Example (basic.rs)
|
||||
//! ```
|
||||
//! use sslrelay::{self, RelayConfig, HandlerCallbacks, CallbackRet, TCPDataType, TLSConfig};
|
||||
//! use sslrelay::{self, CallbackRet, HandlerCallbacks, RelayConfig, TCPDataType, TLSConfig};
|
||||
//!
|
||||
//! // Handler object
|
||||
//! #[derive(Clone)] // Must have Clone trait implemented.
|
||||
|
|
@ -34,7 +38,6 @@
|
|||
//! into data upstream or downstream.
|
||||
//! */
|
||||
//! impl HandlerCallbacks for Handler {
|
||||
//!
|
||||
//! // DownStream non blocking callback (Read Only)
|
||||
//! fn ds_nb_callback(&self, _in_data: Vec<u8>) {
|
||||
//! println!("[CALLBACK] Down Stream Non Blocking CallBack!");
|
||||
|
|
@ -59,7 +62,6 @@
|
|||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//!
|
||||
//! // Create new SSLRelay object
|
||||
//! let mut relay = sslrelay::SSLRelay::new(
|
||||
//! Handler,
|
||||
|
|
@ -68,13 +70,13 @@
|
|||
//! upstream_data_type: TCPDataType::TLS,
|
||||
//! bind_host: "0.0.0.0".to_string(),
|
||||
//! bind_port: "443".to_string(),
|
||||
//! remote_host: "remote.com".to_string(),
|
||||
//! remote_host: |_| "remote.com",
|
||||
//! remote_port: "443".to_string(),
|
||||
//! tls_config: TLSConfig::FILE{
|
||||
//! tls_config: TLSConfig::FILE {
|
||||
//! certificate_path: "./tls.crt".to_string(),
|
||||
//! private_key_path: "./tls.key".to_string(),
|
||||
//! },
|
||||
//! }
|
||||
//! },
|
||||
//! );
|
||||
//!
|
||||
//! // Start listening
|
||||
|
|
@ -83,53 +85,26 @@
|
|||
//! ```
|
||||
|
||||
use openssl::{
|
||||
x509::X509,
|
||||
pkey::PKey,
|
||||
ssl::{
|
||||
SslVerifyMode,
|
||||
SslConnector,
|
||||
SslAcceptor,
|
||||
SslStream,
|
||||
SslFiletype,
|
||||
SslMethod,
|
||||
}
|
||||
ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslStream, SslVerifyMode},
|
||||
x509::X509,
|
||||
};
|
||||
|
||||
use std::net::{
|
||||
TcpListener,
|
||||
TcpStream,
|
||||
Shutdown
|
||||
};
|
||||
use std::net::{Shutdown, TcpListener, TcpStream};
|
||||
|
||||
use std::sync::{
|
||||
Arc,
|
||||
Mutex
|
||||
};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use std::{
|
||||
thread
|
||||
};
|
||||
use std::thread;
|
||||
|
||||
use std::{
|
||||
path::Path,
|
||||
time::Duration,
|
||||
};
|
||||
use std::{path::Path, time::Duration};
|
||||
|
||||
use std::io::{
|
||||
self,
|
||||
Read,
|
||||
Write
|
||||
};
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use std::sync::mpsc::{
|
||||
self,
|
||||
Receiver,
|
||||
Sender
|
||||
};
|
||||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
|
||||
mod data;
|
||||
mod tcp;
|
||||
mod relay;
|
||||
mod tcp;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum FullDuplexTcpState {
|
||||
|
|
@ -163,8 +138,14 @@ pub enum TCPDataType {
|
|||
/// NONE is for when you are not using TLS on the listening/downstream side of the relay.
|
||||
#[derive(Clone)]
|
||||
pub enum TLSConfig {
|
||||
FILE {certificate_path: String, private_key_path: String},
|
||||
DATA {certificate: Vec<u8>, private_key: Vec<u8>},
|
||||
FILE {
|
||||
certificate_path: String,
|
||||
private_key_path: String,
|
||||
},
|
||||
DATA {
|
||||
certificate: Vec<u8>,
|
||||
private_key: Vec<u8>,
|
||||
},
|
||||
NONE,
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +156,8 @@ pub struct RelayConfig {
|
|||
pub upstream_data_type: TCPDataType,
|
||||
pub bind_host: String,
|
||||
pub bind_port: String,
|
||||
pub remote_host: String,
|
||||
pub remote_host: fn(Option<&str>) -> String,
|
||||
//pub remote_host: String,
|
||||
pub remote_port: String,
|
||||
pub tls_config: TLSConfig,
|
||||
}
|
||||
|
|
@ -183,18 +165,23 @@ pub struct RelayConfig {
|
|||
/// CallbackRet for blocking callback functions
|
||||
#[derive(Debug)]
|
||||
pub enum CallbackRet {
|
||||
Relay(Vec<u8>),// Relay data
|
||||
Spoof(Vec<u8>),// Skip relaying and send data back
|
||||
Shutdown,// Shutdown TCP connection
|
||||
Freeze,// Dont send data (pretend as if stream never was recieved)
|
||||
Relay(Vec<u8>), // Relay data
|
||||
Spoof(Vec<u8>), // Skip relaying and send data back
|
||||
Shutdown, // Shutdown TCP connection
|
||||
Freeze, // Dont send data (pretend as if stream never was recieved)
|
||||
}
|
||||
|
||||
/// Callback functions a user may or may not implement.
|
||||
pub trait HandlerCallbacks {
|
||||
fn ds_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
||||
fn ds_nb_callback(&self, _in_data: Vec<u8>){}
|
||||
fn us_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
||||
fn us_nb_callback(&self, _in_data: Vec<u8>){}
|
||||
fn ds_b_callback(&mut self, _in_data: Vec<u8>, _conn_id: u64) -> CallbackRet {
|
||||
CallbackRet::Relay(_in_data)
|
||||
}
|
||||
fn ds_nb_callback(&self, _in_data: Vec<u8>, _conn_id: u64) {}
|
||||
fn us_b_callback(&mut self, _in_data: Vec<u8>, _conn_id: u64) -> CallbackRet {
|
||||
CallbackRet::Relay(_in_data)
|
||||
}
|
||||
fn us_nb_callback(&self, _in_data: Vec<u8>, _conn_id: u64) {}
|
||||
fn set_server_name(&mut self, _server_name: Option<&str>) {}
|
||||
}
|
||||
|
||||
/// The main SSLRelay object.
|
||||
|
|
@ -217,6 +204,7 @@ where
|
|||
ds_inner_m: Arc<Mutex<Option<DownStreamInner>>>,
|
||||
us_inner_m: Arc<Mutex<Option<UpStreamInner>>>,
|
||||
inner_handlers: InnerHandlers<H>,
|
||||
conn_id: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -224,17 +212,15 @@ struct InnerHandlers<H>
|
|||
where
|
||||
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static,
|
||||
{
|
||||
cb: H
|
||||
cb: H,
|
||||
}
|
||||
|
||||
struct DownStreamInner
|
||||
{
|
||||
struct DownStreamInner {
|
||||
ds_stream: DataStreamType,
|
||||
internal_data_buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
struct UpStreamInner
|
||||
{
|
||||
struct UpStreamInner {
|
||||
us_stream: DataStreamType,
|
||||
internal_data_buffer: Vec<u8>
|
||||
internal_data_buffer: Vec<u8>,
|
||||
}
|
||||
202
src/relay.rs
202
src/relay.rs
|
|
@ -1,137 +1,221 @@
|
|||
//! SSLRelay
|
||||
|
||||
use crate::{
|
||||
SSLRelay,
|
||||
HandlerCallbacks,
|
||||
InnerHandlers,
|
||||
TCPDataType,
|
||||
TcpListener,
|
||||
thread,
|
||||
FullDuplexTcp,
|
||||
DataStreamType,
|
||||
RelayConfig,
|
||||
Arc,
|
||||
SslAcceptor,
|
||||
Path,
|
||||
SslMethod,
|
||||
SslFiletype,
|
||||
TLSConfig,
|
||||
PKey,
|
||||
X509,
|
||||
thread, Arc, DataStreamType, FullDuplexTcp, HandlerCallbacks, InnerHandlers, PKey, Path,
|
||||
RelayConfig, SSLRelay, SslAcceptor, SslFiletype, SslMethod, TCPDataType, TLSConfig,
|
||||
TcpListener, X509,
|
||||
};
|
||||
|
||||
impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static> SSLRelay<H> {
|
||||
/// Creates new SSLRelay instance.
|
||||
pub fn new(handlers: H, config: RelayConfig) -> Self {
|
||||
|
||||
SSLRelay {
|
||||
config,
|
||||
handlers: Some(InnerHandlers{cb: handlers}),
|
||||
handlers: Some(InnerHandlers { cb: handlers }),
|
||||
}
|
||||
}
|
||||
/// Starts the SSLRelay connection handling.
|
||||
pub fn start(&mut self) {
|
||||
|
||||
let rhost = self.config.remote_host.clone();
|
||||
let rport = self.config.remote_port.clone();
|
||||
let upstream_data_stream_type = self.config.upstream_data_type;
|
||||
|
||||
let listener = TcpListener::bind(format!("{}:{}", self.config.bind_host.clone(), self.config.bind_port.clone())).unwrap();
|
||||
let listener = TcpListener::bind(format!(
|
||||
"{}:{}",
|
||||
self.config.bind_host.clone(),
|
||||
self.config.bind_port.clone()
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let mut conn_id = 0;
|
||||
match self.config.downstream_data_type {
|
||||
|
||||
TCPDataType::TLS => {
|
||||
|
||||
let acceptor = self.setup_ssl_config(self.config.tls_config.clone());
|
||||
let acceptor = self.setup_ssl_config(&self.config.tls_config);
|
||||
|
||||
for stream in listener.incoming() {
|
||||
|
||||
match stream {
|
||||
Ok(stream) => {
|
||||
|
||||
let acceptor = acceptor.clone();
|
||||
let handler_clone = self.handlers.as_ref().unwrap().clone();
|
||||
let mut handler_clone = self.handlers.as_ref().unwrap().clone();
|
||||
|
||||
let r_host = rhost.clone();
|
||||
let r_port = rport.clone();
|
||||
|
||||
let this_conn_id = conn_id;
|
||||
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) => {println!("[SSLRelay Error] Failed to handle TCP(TLS) connection: {}", _ec)}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
let server_name = stream
|
||||
.ssl()
|
||||
.servername(openssl::ssl::NameType::HOST_NAME);
|
||||
handler_clone.cb.set_server_name(server_name);
|
||||
let remote_host = (r_host)(server_name);
|
||||
|
||||
// FULL DUPLEX OBJECT CREATION HERE
|
||||
match FullDuplexTcp::new(
|
||||
DataStreamType::TLS(stream),
|
||||
upstream_data_stream_type,
|
||||
remote_host,
|
||||
r_port,
|
||||
handler_clone,
|
||||
this_conn_id,
|
||||
) {
|
||||
Ok(mut fdtcp) => fdtcp.handle(),
|
||||
Err(_ec) => {
|
||||
println!(
|
||||
"[SSLRelay Error] Failed to handle TCP(TLS) \
|
||||
connection: {}",
|
||||
_ec
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("[Error] {}", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)}
|
||||
conn_id += 1;
|
||||
}
|
||||
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();
|
||||
|
||||
let this_conn_id = conn_id;
|
||||
thread::spawn(move || {
|
||||
|
||||
// FULL DUPLEX OBJECT CREATION HERE
|
||||
match FullDuplexTcp::new(DataStreamType::RAW(stream), upstream_data_stream_type, r_host, r_port, handler_clone) {
|
||||
match FullDuplexTcp::new(
|
||||
DataStreamType::RAW(stream),
|
||||
upstream_data_stream_type,
|
||||
(r_host)(None),
|
||||
r_port,
|
||||
handler_clone,
|
||||
this_conn_id,
|
||||
) {
|
||||
Ok(mut fdtcp) => fdtcp.handle(),
|
||||
Err(_ec) => println!("[SSLRelay Error] Failed to handle TCP connection: {}", _ec),
|
||||
Err(_ec) => println!(
|
||||
"[SSLRelay Error] Failed to handle TCP connection: {}",
|
||||
_ec
|
||||
),
|
||||
}
|
||||
});
|
||||
},
|
||||
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)}
|
||||
conn_id += 1;
|
||||
}
|
||||
Err(e) => {
|
||||
println!("[Error] Tcp Connection Failed: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_ssl_config(&self, tls_config: TLSConfig) -> Arc<SslAcceptor> {
|
||||
|
||||
fn setup_ssl_config(&self, tls_config: &TLSConfig) -> Arc<SslAcceptor> {
|
||||
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
||||
|
||||
match tls_config {
|
||||
TLSConfig::FILE{certificate_path, private_key_path} => {
|
||||
|
||||
TLSConfig::FILE {
|
||||
certificate_path,
|
||||
private_key_path,
|
||||
} => {
|
||||
if !Path::new(&private_key_path).exists() {
|
||||
panic!("[-] [{}] does not exist!", private_key_path);
|
||||
}
|
||||
if !Path::new(&certificate_path).exists() {
|
||||
panic!("[-] [{}] does not exist!", certificate_path);
|
||||
}
|
||||
acceptor.set_private_key_file(private_key_path, SslFiletype::PEM).unwrap();
|
||||
acceptor.set_certificate_chain_file(certificate_path).unwrap();
|
||||
acceptor
|
||||
.set_private_key_file(private_key_path, SslFiletype::PEM)
|
||||
.unwrap();
|
||||
acceptor
|
||||
.set_certificate_chain_file(certificate_path)
|
||||
.unwrap();
|
||||
acceptor.check_private_key().unwrap();
|
||||
},
|
||||
TLSConfig::DATA{certificate, private_key} => {
|
||||
}
|
||||
TLSConfig::DATA {
|
||||
certificate,
|
||||
private_key,
|
||||
} => {
|
||||
let x_509_certificate = X509::from_pem(certificate.as_slice()).unwrap();
|
||||
let private_key = PKey::private_key_from_pem(private_key.as_slice()).unwrap();
|
||||
acceptor.set_certificate(x_509_certificate.as_ref()).unwrap();
|
||||
acceptor
|
||||
.set_certificate(x_509_certificate.as_ref())
|
||||
.unwrap();
|
||||
acceptor.set_private_key(private_key.as_ref()).unwrap();
|
||||
},
|
||||
}
|
||||
TLSConfig::NONE => {
|
||||
panic!("[SSLRelay Error] Specified NONE for TLSConfig and downstream_data_type as TLS.");
|
||||
panic!(
|
||||
"[SSLRelay Error] Specified NONE for TLSConfig and downstream_data_type as \
|
||||
TLS."
|
||||
);
|
||||
}
|
||||
}
|
||||
Arc::new(acceptor.build())
|
||||
}
|
||||
}// SSLRelay
|
||||
|
||||
// fn setup_ssl_config(&self, tls_configs: &[(&[&str], TLSConfig)]) -> AcceptorDb {
|
||||
// let mut acceptor_db = AcceptorDb {
|
||||
// acceptors: HashMap::new(),
|
||||
// };
|
||||
// for (names, tls_config) in tls_configs {
|
||||
// let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
||||
// match tls_config {
|
||||
// TLSConfig::FILE {
|
||||
// certificate_path,
|
||||
// private_key_path,
|
||||
// } => {
|
||||
// if !Path::new(&private_key_path).exists() {
|
||||
// panic!("[-] [{}] does not exist!", private_key_path);
|
||||
// }
|
||||
// if !Path::new(&certificate_path).exists() {
|
||||
// panic!("[-] [{}] does not exist!", certificate_path);
|
||||
// }
|
||||
// acceptor
|
||||
// .set_private_key_file(private_key_path, SslFiletype::PEM)
|
||||
// .unwrap();
|
||||
// acceptor
|
||||
// .set_certificate_chain_file(certificate_path)
|
||||
// .unwrap();
|
||||
// acceptor.check_private_key().unwrap();
|
||||
// }
|
||||
// TLSConfig::DATA {
|
||||
// certificate,
|
||||
// private_key,
|
||||
// } => {
|
||||
// let x_509_certificate = X509::from_pem(certificate.as_slice()).unwrap();
|
||||
// let private_key = PKey::private_key_from_pem(private_key.as_slice()).unwrap();
|
||||
// acceptor
|
||||
// .set_certificate(x_509_certificate.as_ref())
|
||||
// .unwrap();
|
||||
// acceptor.set_private_key(private_key.as_ref()).unwrap();
|
||||
// }
|
||||
// TLSConfig::NONE => {
|
||||
// panic!(
|
||||
// "[SSLRelay Error] Specified NONE for TLSConfig and downstream_data_type as \
|
||||
// TLS."
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// let acceptor = Arc::new(acceptor.build());
|
||||
// for name in *names {
|
||||
// acceptor_db.acceptors.insert(name.to_string(), acceptor.clone());
|
||||
// }
|
||||
// }
|
||||
// acceptor_db
|
||||
// }
|
||||
} // SSLRelay
|
||||
|
||||
// struct AcceptorDb {
|
||||
// acceptors: HashMap<String, Arc<SslAcceptor>>,
|
||||
// }
|
||||
|
|
|
|||
287
src/tcp.rs
287
src/tcp.rs
|
|
@ -1,63 +1,76 @@
|
|||
use crate::{
|
||||
FullDuplexTcp,
|
||||
HandlerCallbacks,
|
||||
DataStreamType,
|
||||
TCPDataType,
|
||||
Duration,
|
||||
Arc,
|
||||
Mutex,
|
||||
DownStreamInner,
|
||||
UpStreamInner,
|
||||
InnerHandlers,
|
||||
Shutdown,
|
||||
Sender,
|
||||
Receiver,
|
||||
FullDuplexTcpState,
|
||||
DataPipe,
|
||||
mpsc,
|
||||
thread,
|
||||
CallbackRet,
|
||||
TcpStream,
|
||||
SslVerifyMode,
|
||||
SslConnector,
|
||||
SslMethod,
|
||||
mpsc, thread, Arc, CallbackRet, DataPipe, DataStreamType, DownStreamInner, Duration,
|
||||
FullDuplexTcp, FullDuplexTcpState, HandlerCallbacks, InnerHandlers, Mutex, Receiver, Sender,
|
||||
Shutdown, SslConnector, SslMethod, SslVerifyMode, TCPDataType, TcpStream, UpStreamInner,
|
||||
};
|
||||
|
||||
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> {
|
||||
|
||||
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>,
|
||||
conn_id: u64,
|
||||
) -> 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))); },
|
||||
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()) {
|
||||
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(); },
|
||||
DataStreamType::RAW(s) => {
|
||||
let _ = s.shutdown(Shutdown::Both);
|
||||
}
|
||||
DataStreamType::TLS(mut s) => {
|
||||
let _ = s.shutdown();
|
||||
}
|
||||
}
|
||||
return Err(ec);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(
|
||||
FullDuplexTcp {
|
||||
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()}))),
|
||||
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,
|
||||
conn_id,
|
||||
})
|
||||
}
|
||||
|
||||
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 conn_id = self.conn_id;
|
||||
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();
|
||||
|
|
@ -66,22 +79,29 @@ impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'stat
|
|||
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);
|
||||
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);
|
||||
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
|
||||
|
|
@ -95,43 +115,70 @@ impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'stat
|
|||
let in_data = data.clone();
|
||||
|
||||
thread::spawn(move || {
|
||||
inner_handlers_clone.cb.us_nb_callback(in_data);
|
||||
inner_handlers_clone.cb.us_nb_callback(in_data, conn_id);
|
||||
});
|
||||
|
||||
match self.inner_handlers.cb.us_b_callback(data) {
|
||||
match self.inner_handlers.cb.us_b_callback(data, conn_id) {
|
||||
CallbackRet::Relay(retdata) => {
|
||||
match ds_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
||||
Ok(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
||||
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(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
||||
Self::handle_error(
|
||||
format!(
|
||||
"Failed to send data write to DownStream \
|
||||
thread: {}",
|
||||
e
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
CallbackRet::Freeze => {},
|
||||
}
|
||||
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());
|
||||
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());
|
||||
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
|
||||
*/
|
||||
|
|
@ -140,92 +187,143 @@ impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'stat
|
|||
let in_data = data.clone();
|
||||
|
||||
thread::spawn(move || {
|
||||
inner_handlers_clone.cb.ds_nb_callback(in_data);
|
||||
inner_handlers_clone.cb.ds_nb_callback(in_data, conn_id);
|
||||
});
|
||||
|
||||
match self.inner_handlers.cb.ds_b_callback(data) {
|
||||
match self.inner_handlers.cb.ds_b_callback(data, conn_id) {
|
||||
CallbackRet::Relay(retdata) => {
|
||||
match us_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
||||
Ok(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
Self::handle_error(format!("Failed to send data write to UpStream thread: {}", e).as_str());
|
||||
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(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
||||
Self::handle_error(
|
||||
format!(
|
||||
"Failed to send data write to DownStream \
|
||||
thread: {}",
|
||||
e
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
CallbackRet::Freeze => {},
|
||||
}
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
Self::handle_error(
|
||||
format!("Failed to send Shutdown signal to UpStream thread: {}", e)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}// State Receiver
|
||||
} // State Receiver
|
||||
}
|
||||
}
|
||||
|
||||
fn connect_endpoint(stream_data_type: TCPDataType, remote_host: String, remote_port: String) -> Result<DataStreamType, i8> {
|
||||
|
||||
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());
|
||||
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);
|
||||
|
||||
|
|
@ -234,7 +332,14 @@ impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'stat
|
|||
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());
|
||||
Self::handle_error(
|
||||
format!(
|
||||
"Can't connect to remote host: {}\nErr: {}",
|
||||
format!("{}:{}", remote_host, remote_port),
|
||||
e
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
return Result::Err(-1);
|
||||
}
|
||||
};
|
||||
|
|
@ -242,12 +347,16 @@ impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'stat
|
|||
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());
|
||||
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)));
|
||||
let _ = s
|
||||
.get_ref()
|
||||
.set_read_timeout(Some(Duration::from_millis(50)));
|
||||
return Ok(DataStreamType::TLS(s));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue