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
|
||||||
739
src/data.rs
739
src/data.rs
|
|
@ -1,441 +1,370 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
DownStreamInner,
|
io, mpsc, DataPipe, DataStreamType, DownStreamInner, Duration, FullDuplexTcpState, Read,
|
||||||
UpStreamInner,
|
Receiver, Sender, Shutdown, UpStreamInner, Write,
|
||||||
FullDuplexTcpState,
|
|
||||||
DataPipe,
|
|
||||||
DataStreamType,
|
|
||||||
Sender,
|
|
||||||
Receiver,
|
|
||||||
Shutdown,
|
|
||||||
mpsc,
|
|
||||||
Duration,
|
|
||||||
Read,
|
|
||||||
Write,
|
|
||||||
io,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl DownStreamInner {
|
impl DownStreamInner {
|
||||||
|
fn handle_error(error_description: &str) {
|
||||||
|
println!("[SSLRelay DownStream Thread Error]: {}", error_description);
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_error(error_description: &str) {
|
pub fn ds_handler(self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
||||||
println!("[SSLRelay DownStream Thread Error]: {}", error_description);
|
match &self.ds_stream {
|
||||||
}
|
DataStreamType::RAW(_) => self.handle_raw(data_out, data_in),
|
||||||
|
DataStreamType::TLS(_) => self.handle_tls(data_out, data_in),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ds_handler(self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
match &self.ds_stream {
|
loop {
|
||||||
DataStreamType::RAW(_) => self.handle_raw(data_out, data_in),
|
match data_in.recv_timeout(Duration::from_millis(50)) {
|
||||||
DataStreamType::TLS(_) => self.handle_tls(data_out, data_in),
|
// DataPipe Received
|
||||||
}
|
Ok(data_received) => match data_received {
|
||||||
}
|
DataPipe::DataWrite(data) => {
|
||||||
|
match raw_stream.write_all(&data) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(_e) => {
|
||||||
|
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 => {}
|
||||||
|
mpsc::RecvTimeoutError::Disconnected => {
|
||||||
|
Self::handle_error("DownStream data_in channel is disconnected!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
} // End of data_in receive
|
||||||
|
|
||||||
fn handle_raw(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
// If received data
|
||||||
|
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(),
|
||||||
|
)) {
|
||||||
|
//Self::handle_error(format!("Failed to send UpStreamWrite to main thread: {}", e).as_str());
|
||||||
|
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut raw_stream = match &self.ds_stream {
|
self.internal_data_buffer.clear();
|
||||||
DataStreamType::RAW(ref s) => s,
|
} else if byte_count == 0 || byte_count == -2 {
|
||||||
_ => return,
|
let _ = data_out.send(FullDuplexTcpState::DownStreamShutDown);
|
||||||
};
|
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||||
|
return;
|
||||||
|
} else if byte_count == -1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
match data_in.recv_timeout(Duration::from_millis(50)) {
|
loop {
|
||||||
|
match data_in.recv_timeout(Duration::from_millis(50)) {
|
||||||
|
// DataPipe Received
|
||||||
|
Ok(data_received) => match data_received {
|
||||||
|
DataPipe::DataWrite(data) => {
|
||||||
|
match tls_stream.write_all(&data) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(_e) => {
|
||||||
|
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 => {}
|
||||||
|
mpsc::RecvTimeoutError::Disconnected => {
|
||||||
|
Self::handle_error("DownStream data_in channel is disconnected!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
} // End of data_in receive
|
||||||
|
|
||||||
// DataPipe Received
|
// If received data
|
||||||
Ok(data_received) => {
|
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(),
|
||||||
|
)) {
|
||||||
|
//Self::handle_error(format!("Failed to send UpStreamWrite to main thread: {}", e).as_str());
|
||||||
|
let _ = tls_stream.shutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
match data_received {
|
self.internal_data_buffer.clear();
|
||||||
DataPipe::DataWrite(data) => {
|
} 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 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match raw_stream.write_all(&data) {
|
fn get_data_stream<S: Read>(stream: &mut S, internal_data_buffer: &mut Vec<u8>) -> Option<i64> {
|
||||||
Ok(()) => {},
|
let mut data_length: i64 = 0;
|
||||||
Err(_e) => {
|
|
||||||
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();
|
|
||||||
|
|
||||||
},
|
loop {
|
||||||
DataPipe::Shutdown => {
|
let mut r_buf = [0; 1024];
|
||||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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
|
|
||||||
|
|
||||||
// If received data
|
match stream.read(&mut r_buf) {
|
||||||
if let Some(byte_count) = Self::get_data_stream(&mut raw_stream, &mut self.internal_data_buffer) {
|
Ok(bytes_read) => {
|
||||||
if byte_count > 0 {
|
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);
|
||||||
|
*/
|
||||||
|
|
||||||
if let Err(_e) = data_out.send(FullDuplexTcpState::UpStreamWrite(self.internal_data_buffer.clone())) {
|
//let _bw = self.internal_data_buffer.write(&tmp_buf).unwrap();
|
||||||
|
|
||||||
//Self::handle_error(format!("Failed to send UpStreamWrite to main thread: {}", e).as_str());
|
let _bw = internal_data_buffer
|
||||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
.write(r_buf.split_at(bytes_read).0)
|
||||||
return;
|
.unwrap();
|
||||||
}
|
data_length += bytes_read as i64;
|
||||||
|
} else {
|
||||||
self.internal_data_buffer.clear();
|
println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
}
|
||||||
} else if byte_count == 0 || byte_count == -2 {
|
}
|
||||||
|
Err(e) => match e.kind() {
|
||||||
let _ = data_out.send(FullDuplexTcpState::DownStreamShutDown);
|
io::ErrorKind::WouldBlock => {
|
||||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
if data_length == 0 {
|
||||||
return;
|
data_length = -1;
|
||||||
|
}
|
||||||
} else if byte_count == -1 {
|
break;
|
||||||
continue;
|
}
|
||||||
}
|
io::ErrorKind::ConnectionReset => {
|
||||||
} else {
|
data_length = -2;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
_ => {
|
||||||
}
|
println!("[!!!downstream] Got error: {}", e);
|
||||||
|
}
|
||||||
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 Some(data_length);
|
||||||
_ => return,
|
}
|
||||||
};
|
|
||||||
|
|
||||||
loop {
|
|
||||||
|
|
||||||
match data_in.recv_timeout(Duration::from_millis(50)) {
|
|
||||||
|
|
||||||
// DataPipe Received
|
|
||||||
Ok(data_received) => {
|
|
||||||
|
|
||||||
match data_received {
|
|
||||||
DataPipe::DataWrite(data) => {
|
|
||||||
|
|
||||||
match tls_stream.write_all(&data) {
|
|
||||||
Ok(()) => {},
|
|
||||||
Err(_e) => {
|
|
||||||
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 => {},
|
|
||||||
mpsc::RecvTimeoutError::Disconnected => {
|
|
||||||
Self::handle_error("DownStream data_in channel is disconnected!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}// 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 byte_count > 0 {
|
|
||||||
|
|
||||||
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();
|
|
||||||
data_length += bytes_read as i64;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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);}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Some(data_length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl UpStreamInner {
|
impl UpStreamInner {
|
||||||
|
fn handle_error(error_description: &str) {
|
||||||
|
println!("[SSLRelay UpStream Thread Error]: {}", error_description);
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_error(error_description: &str) {
|
pub fn us_handler(self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
||||||
println!("[SSLRelay UpStream Thread Error]: {}", error_description);
|
match &self.us_stream {
|
||||||
}
|
DataStreamType::RAW(_) => self.handle_raw(data_out, data_in),
|
||||||
|
DataStreamType::TLS(_) => self.handle_tls(data_out, data_in),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn us_handler(self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
match &self.us_stream {
|
loop {
|
||||||
DataStreamType::RAW(_) => self.handle_raw(data_out, data_in),
|
match data_in.recv_timeout(Duration::from_millis(50)) {
|
||||||
DataStreamType::TLS(_) => self.handle_tls(data_out, data_in),
|
Ok(data_received) => match data_received {
|
||||||
}
|
DataPipe::DataWrite(data) => {
|
||||||
|
match raw_stream.write_all(&data) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(_e) => {
|
||||||
|
Self::handle_error("Failed to write data to UpStream tcp stream!");
|
||||||
|
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
||||||
|
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 => {}
|
||||||
|
mpsc::RecvTimeoutError::Disconnected => {
|
||||||
|
Self::handle_error("UpStream data_in channel is disconnected!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
} // End of data_in receive
|
||||||
|
|
||||||
}
|
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(),
|
||||||
|
)) {
|
||||||
|
//Self::handle_error(format!("Failed to send DownStreamWrite to main thread: {}", e).as_str());
|
||||||
|
let _ = raw_stream.shutdown(Shutdown::Both);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_raw(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
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;
|
||||||
|
} else if byte_count == -1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut raw_stream = match self.us_stream {
|
fn handle_tls(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
||||||
DataStreamType::RAW(ref s) => s,
|
let mut tls_stream = match self.us_stream {
|
||||||
_ => return,
|
DataStreamType::TLS(ref mut s) => s,
|
||||||
};
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
match data_in.recv_timeout(Duration::from_millis(50)) {
|
||||||
|
Ok(data_received) => match data_received {
|
||||||
|
DataPipe::DataWrite(data) => {
|
||||||
|
match tls_stream.write_all(&data) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(_e) => {
|
||||||
|
Self::handle_error("Failed to write data to UpStream tcp stream!");
|
||||||
|
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
||||||
|
let _ = tls_stream.shutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = tls_stream.flush();
|
||||||
|
}
|
||||||
|
DataPipe::Shutdown => {
|
||||||
|
let _ = tls_stream.shutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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
|
||||||
|
|
||||||
match data_in.recv_timeout(Duration::from_millis(50)) {
|
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(),
|
||||||
|
)) {
|
||||||
|
//Self::handle_error(format!("Failed to send DownStreamWrite to main thread: {}", e).as_str());
|
||||||
|
let _ = tls_stream.shutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(data_received) => {
|
self.internal_data_buffer.clear();
|
||||||
|
} else if byte_count == 0 || byte_count == -2 {
|
||||||
|
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
||||||
|
let _ = tls_stream.shutdown();
|
||||||
|
return;
|
||||||
|
} else if byte_count == -1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match data_received {
|
fn get_data_stream<S: Read>(stream: &mut S, internal_data_buffer: &mut Vec<u8>) -> Option<i64> {
|
||||||
DataPipe::DataWrite(data) => {
|
let mut data_length: i64 = 0;
|
||||||
|
|
||||||
match raw_stream.write_all(&data) {
|
loop {
|
||||||
Ok(()) => {},
|
let mut r_buf = [0; 1024];
|
||||||
Err(_e) => {
|
|
||||||
Self::handle_error("Failed to write data to UpStream tcp stream!");
|
|
||||||
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
|
||||||
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 => {},
|
|
||||||
mpsc::RecvTimeoutError::Disconnected => {
|
|
||||||
Self::handle_error("UpStream data_in channel is disconnected!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}// End of data_in receive
|
|
||||||
|
|
||||||
if let Some(byte_count) = Self::get_data_stream(&mut raw_stream, &mut self.internal_data_buffer) {
|
match stream.read(&mut r_buf) {
|
||||||
if byte_count > 0 {
|
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);
|
||||||
|
*/
|
||||||
|
|
||||||
if let Err(_e) = data_out.send(FullDuplexTcpState::DownStreamWrite(self.internal_data_buffer.clone())) {
|
//let _bw = self.internal_data_buffer.write(&tmp_buf).unwrap();
|
||||||
|
|
||||||
//Self::handle_error(format!("Failed to send DownStreamWrite to main thread: {}", e).as_str());
|
let _bw = internal_data_buffer
|
||||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
.write(r_buf.split_at(bytes_read).0)
|
||||||
return;
|
.unwrap();
|
||||||
}
|
data_length += bytes_read as i64;
|
||||||
|
} else {
|
||||||
self.internal_data_buffer.clear();
|
println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
}
|
||||||
} else if byte_count == 0 || byte_count == -2 {
|
}
|
||||||
|
Err(e) => match e.kind() {
|
||||||
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
io::ErrorKind::WouldBlock => {
|
||||||
let _ = raw_stream.shutdown(Shutdown::Both);
|
if data_length == 0 {
|
||||||
return;
|
data_length = -1;
|
||||||
} else if byte_count == -1 {
|
}
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
io::ErrorKind::ConnectionReset => {
|
||||||
}
|
data_length = -2;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
fn handle_tls(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) {
|
println!("[!!!upstream] Got error: {}", e);
|
||||||
|
}
|
||||||
let mut tls_stream = match self.us_stream {
|
},
|
||||||
DataStreamType::TLS(ref mut s) => s,
|
}
|
||||||
_ => return,
|
}
|
||||||
};
|
return Some(data_length);
|
||||||
|
}
|
||||||
loop {
|
|
||||||
|
|
||||||
match data_in.recv_timeout(Duration::from_millis(50)) {
|
|
||||||
|
|
||||||
Ok(data_received) => {
|
|
||||||
|
|
||||||
match data_received {
|
|
||||||
DataPipe::DataWrite(data) => {
|
|
||||||
|
|
||||||
match tls_stream.write_all(&data) {
|
|
||||||
Ok(()) => {},
|
|
||||||
Err(_e) => {
|
|
||||||
Self::handle_error("Failed to write data to UpStream tcp stream!");
|
|
||||||
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown);
|
|
||||||
let _ = tls_stream.shutdown();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let _ = tls_stream.flush();
|
|
||||||
},
|
|
||||||
DataPipe::Shutdown => {
|
|
||||||
let _ = tls_stream.shutdown();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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
|
|
||||||
|
|
||||||
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())) {
|
|
||||||
|
|
||||||
//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;
|
|
||||||
} 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();
|
|
||||||
data_length += bytes_read as i64;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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);}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Some(data_length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
258
src/lib.rs
258
src/lib.rs
|
|
@ -4,157 +4,132 @@
|
||||||
//! This library allows you to implement callback functions for upstream and downstream traffic.
|
//! 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).
|
//! These callbacks can R/W the data from a stream(Blocking) or only R the data(Non-Blocking).
|
||||||
//!```
|
//!```
|
||||||
//!pub trait HandlerCallbacks {
|
//! pub trait HandlerCallbacks {
|
||||||
//! fn ds_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
//! fn ds_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {
|
||||||
//! fn ds_nb_callback(&self, _in_data: Vec<u8>){}
|
//! CallbackRet::Relay(_in_data)
|
||||||
//! 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_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 blocking callbacks return an enum called CallbackRet with four different variants.
|
||||||
//! The variants control the flow of the tcp stream.
|
//! The variants control the flow of the tcp stream.
|
||||||
//!```
|
//!```
|
||||||
//! pub enum CallbackRet {
|
//! pub enum CallbackRet {
|
||||||
//! Relay(Vec<u8>),// Relay data
|
//! Relay(Vec<u8>), // Relay data
|
||||||
//! Spoof(Vec<u8>),// Skip relaying and send data back
|
//! Spoof(Vec<u8>), // Skip relaying and send data back
|
||||||
//! Shutdown,// Shutdown TCP connection
|
//! Shutdown, // Shutdown TCP connection
|
||||||
//! Freeze,// Dont send data (pretend as if stream never was recieved)
|
//! Freeze, // Dont send data (pretend as if stream never was recieved)
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//! ## Example (basic.rs)
|
//! ## Example (basic.rs)
|
||||||
//! ```
|
//! ```
|
||||||
//! use sslrelay::{self, RelayConfig, HandlerCallbacks, CallbackRet, TCPDataType, TLSConfig};
|
//! use sslrelay::{self, CallbackRet, HandlerCallbacks, RelayConfig, TCPDataType, TLSConfig};
|
||||||
//!
|
//!
|
||||||
//! // Handler object
|
//! // Handler object
|
||||||
//! #[derive(Clone)] // Must have Clone trait implemented.
|
//! #[derive(Clone)] // Must have Clone trait implemented.
|
||||||
//! struct Handler;
|
//! struct Handler;
|
||||||
//!
|
//!
|
||||||
//! /*
|
//! /*
|
||||||
//! Callback traits that can be used to read or inject data
|
//! Callback traits that can be used to read or inject data
|
||||||
//! into data upstream or downstream.
|
//! into data upstream or downstream.
|
||||||
//! */
|
//! */
|
||||||
//! impl HandlerCallbacks for Handler {
|
//! 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!");
|
||||||
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // DownStream non blocking callback (Read Only)
|
//! // DownStream blocking callback (Read & Write)
|
||||||
//! fn ds_nb_callback(&self, _in_data: Vec<u8>) {
|
//! fn ds_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {
|
||||||
//! println!("[CALLBACK] Down Stream Non Blocking CallBack!");
|
//! println!("[CALLBACK] Down Stream Blocking CallBack!");
|
||||||
//! }
|
//! CallbackRet::Relay(_in_data)
|
||||||
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // DownStream blocking callback (Read & Write)
|
//! // UpStream non blocking callback (Read Only)
|
||||||
//! fn ds_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {
|
//! fn us_nb_callback(&self, _in_data: Vec<u8>) {
|
||||||
//! println!("[CALLBACK] Down Stream Blocking CallBack!");
|
//! println!("[CALLBACK] Up Stream Non Blocking CallBack!");
|
||||||
//! CallbackRet::Relay(_in_data)
|
//! }
|
||||||
//! }
|
|
||||||
//!
|
//!
|
||||||
//! // UpStream non blocking callback (Read Only)
|
//! // UpStream blocking callback (Read & Write)
|
||||||
//! fn us_nb_callback(&self, _in_data: Vec<u8>) {
|
//! fn us_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {
|
||||||
//! println!("[CALLBACK] Up Stream Non Blocking CallBack!");
|
//! println!("[CALLBACK] Up Stream Blocking CallBack!");
|
||||||
//! }
|
//! CallbackRet::Relay(_in_data)
|
||||||
//!
|
//! }
|
||||||
//! // UpStream blocking callback (Read & Write)
|
|
||||||
//! fn us_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {
|
|
||||||
//! println!("[CALLBACK] Up Stream Blocking CallBack!");
|
|
||||||
//! CallbackRet::Relay(_in_data)
|
|
||||||
//! }
|
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! 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",
|
||||||
|
//! remote_port: "443".to_string(),
|
||||||
|
//! tls_config: TLSConfig::FILE {
|
||||||
|
//! certificate_path: "./tls.crt".to_string(),
|
||||||
|
//! private_key_path: "./tls.key".to_string(),
|
||||||
|
//! },
|
||||||
|
//! },
|
||||||
|
//! );
|
||||||
//!
|
//!
|
||||||
//! // Create new SSLRelay object
|
//! // Start listening
|
||||||
//! let mut relay = sslrelay::SSLRelay::new(
|
//! relay.start();
|
||||||
//! 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();
|
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use openssl::{
|
use openssl::{
|
||||||
x509::X509,
|
pkey::PKey,
|
||||||
pkey::PKey,
|
ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslStream, SslVerifyMode},
|
||||||
ssl::{
|
x509::X509,
|
||||||
SslVerifyMode,
|
|
||||||
SslConnector,
|
|
||||||
SslAcceptor,
|
|
||||||
SslStream,
|
|
||||||
SslFiletype,
|
|
||||||
SslMethod,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::net::{
|
use std::net::{Shutdown, TcpListener, TcpStream};
|
||||||
TcpListener,
|
|
||||||
TcpStream,
|
|
||||||
Shutdown
|
|
||||||
};
|
|
||||||
|
|
||||||
use std::sync::{
|
use std::sync::{Arc, Mutex};
|
||||||
Arc,
|
|
||||||
Mutex
|
|
||||||
};
|
|
||||||
|
|
||||||
use std::{
|
use std::thread;
|
||||||
thread
|
|
||||||
};
|
|
||||||
|
|
||||||
use std::{
|
use std::{path::Path, time::Duration};
|
||||||
path::Path,
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use std::io::{
|
use std::io::{self, Read, Write};
|
||||||
self,
|
|
||||||
Read,
|
|
||||||
Write
|
|
||||||
};
|
|
||||||
|
|
||||||
use std::sync::mpsc::{
|
use std::sync::mpsc::{self, Receiver, Sender};
|
||||||
self,
|
|
||||||
Receiver,
|
|
||||||
Sender
|
|
||||||
};
|
|
||||||
|
|
||||||
mod data;
|
mod data;
|
||||||
mod tcp;
|
|
||||||
mod relay;
|
mod relay;
|
||||||
|
mod tcp;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum FullDuplexTcpState {
|
enum FullDuplexTcpState {
|
||||||
DownStreamWrite(Vec<u8>),
|
DownStreamWrite(Vec<u8>),
|
||||||
UpStreamWrite(Vec<u8>),
|
UpStreamWrite(Vec<u8>),
|
||||||
DownStreamShutDown,
|
DownStreamShutDown,
|
||||||
UpStreamShutDown,
|
UpStreamShutDown,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum DataPipe {
|
enum DataPipe {
|
||||||
DataWrite(Vec<u8>),
|
DataWrite(Vec<u8>),
|
||||||
Shutdown,
|
Shutdown,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DataStreamType {
|
enum DataStreamType {
|
||||||
RAW(TcpStream),
|
RAW(TcpStream),
|
||||||
TLS(SslStream<TcpStream>),
|
TLS(SslStream<TcpStream>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specifies the upstream or downstream data type (TLS or RAW).
|
/// Specifies the upstream or downstream data type (TLS or RAW).
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum TCPDataType {
|
pub enum TCPDataType {
|
||||||
TLS,
|
TLS,
|
||||||
RAW,
|
RAW,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TLSConfig is used to specify TLS options.
|
/// TLSConfig is used to specify TLS options.
|
||||||
|
|
@ -163,78 +138,89 @@ pub enum TCPDataType {
|
||||||
/// NONE is for when you are not using TLS on the listening/downstream side of the relay.
|
/// NONE is for when you are not using TLS on the listening/downstream side of the relay.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum TLSConfig {
|
pub enum TLSConfig {
|
||||||
FILE {certificate_path: String, private_key_path: String},
|
FILE {
|
||||||
DATA {certificate: Vec<u8>, private_key: Vec<u8>},
|
certificate_path: String,
|
||||||
NONE,
|
private_key_path: String,
|
||||||
|
},
|
||||||
|
DATA {
|
||||||
|
certificate: Vec<u8>,
|
||||||
|
private_key: Vec<u8>,
|
||||||
|
},
|
||||||
|
NONE,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Relay Config structure for passing into the SSLRelay::new() config parameter.
|
/// Relay Config structure for passing into the SSLRelay::new() config parameter.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RelayConfig {
|
pub struct RelayConfig {
|
||||||
pub downstream_data_type: TCPDataType,
|
pub downstream_data_type: TCPDataType,
|
||||||
pub upstream_data_type: TCPDataType,
|
pub upstream_data_type: TCPDataType,
|
||||||
pub bind_host: String,
|
pub bind_host: String,
|
||||||
pub bind_port: String,
|
pub bind_port: String,
|
||||||
pub remote_host: String,
|
pub remote_host: fn(Option<&str>) -> String,
|
||||||
pub remote_port: String,
|
//pub remote_host: String,
|
||||||
pub tls_config: TLSConfig,
|
pub remote_port: String,
|
||||||
|
pub tls_config: TLSConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CallbackRet for blocking callback functions
|
/// CallbackRet for blocking callback functions
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CallbackRet {
|
pub enum CallbackRet {
|
||||||
Relay(Vec<u8>),// Relay data
|
Relay(Vec<u8>), // Relay data
|
||||||
Spoof(Vec<u8>),// Skip relaying and send data back
|
Spoof(Vec<u8>), // Skip relaying and send data back
|
||||||
Shutdown,// Shutdown TCP connection
|
Shutdown, // Shutdown TCP connection
|
||||||
Freeze,// Dont send data (pretend as if stream never was recieved)
|
Freeze, // Dont send data (pretend as if stream never was recieved)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Callback functions a user may or may not implement.
|
/// Callback functions a user may or may not implement.
|
||||||
pub trait HandlerCallbacks {
|
pub trait HandlerCallbacks {
|
||||||
fn ds_b_callback(&mut self, _in_data: Vec<u8>) -> CallbackRet {CallbackRet::Relay(_in_data)}
|
fn ds_b_callback(&mut self, _in_data: Vec<u8>, _conn_id: u64) -> CallbackRet {
|
||||||
fn ds_nb_callback(&self, _in_data: Vec<u8>){}
|
CallbackRet::Relay(_in_data)
|
||||||
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_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.
|
/// The main SSLRelay object.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SSLRelay<H>
|
pub struct SSLRelay<H>
|
||||||
where
|
where
|
||||||
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static,
|
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static,
|
||||||
{
|
{
|
||||||
config: RelayConfig,
|
config: RelayConfig,
|
||||||
handlers: Option<InnerHandlers<H>>,
|
handlers: Option<InnerHandlers<H>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct FullDuplexTcp<H>
|
struct FullDuplexTcp<H>
|
||||||
where
|
where
|
||||||
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static,
|
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static,
|
||||||
{
|
{
|
||||||
remote_host: String,
|
remote_host: String,
|
||||||
remote_port: String,
|
remote_port: String,
|
||||||
ds_inner_m: Arc<Mutex<Option<DownStreamInner>>>,
|
ds_inner_m: Arc<Mutex<Option<DownStreamInner>>>,
|
||||||
us_inner_m: Arc<Mutex<Option<UpStreamInner>>>,
|
us_inner_m: Arc<Mutex<Option<UpStreamInner>>>,
|
||||||
inner_handlers: InnerHandlers<H>,
|
inner_handlers: InnerHandlers<H>,
|
||||||
|
conn_id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DownStreamInner
|
struct DownStreamInner {
|
||||||
{
|
ds_stream: DataStreamType,
|
||||||
ds_stream: DataStreamType,
|
internal_data_buffer: Vec<u8>,
|
||||||
internal_data_buffer: Vec<u8>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UpStreamInner
|
struct UpStreamInner {
|
||||||
{
|
us_stream: DataStreamType,
|
||||||
us_stream: DataStreamType,
|
internal_data_buffer: Vec<u8>,
|
||||||
internal_data_buffer: Vec<u8>
|
|
||||||
}
|
}
|
||||||
322
src/relay.rs
322
src/relay.rs
|
|
@ -1,137 +1,221 @@
|
||||||
//! SSLRelay
|
//! SSLRelay
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
SSLRelay,
|
thread, Arc, DataStreamType, FullDuplexTcp, HandlerCallbacks, InnerHandlers, PKey, Path,
|
||||||
HandlerCallbacks,
|
RelayConfig, SSLRelay, SslAcceptor, SslFiletype, SslMethod, TCPDataType, TLSConfig,
|
||||||
InnerHandlers,
|
TcpListener, X509,
|
||||||
TCPDataType,
|
|
||||||
TcpListener,
|
|
||||||
thread,
|
|
||||||
FullDuplexTcp,
|
|
||||||
DataStreamType,
|
|
||||||
RelayConfig,
|
|
||||||
Arc,
|
|
||||||
SslAcceptor,
|
|
||||||
Path,
|
|
||||||
SslMethod,
|
|
||||||
SslFiletype,
|
|
||||||
TLSConfig,
|
|
||||||
PKey,
|
|
||||||
X509,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static> SSLRelay<H> {
|
impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static> SSLRelay<H> {
|
||||||
/// Creates new SSLRelay instance.
|
/// Creates new SSLRelay instance.
|
||||||
pub fn new(handlers: H, config: RelayConfig) -> Self {
|
pub fn new(handlers: H, config: RelayConfig) -> Self {
|
||||||
|
SSLRelay {
|
||||||
|
config,
|
||||||
|
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;
|
||||||
|
|
||||||
SSLRelay {
|
let listener = TcpListener::bind(format!(
|
||||||
config,
|
"{}:{}",
|
||||||
handlers: Some(InnerHandlers{cb: handlers}),
|
self.config.bind_host.clone(),
|
||||||
}
|
self.config.bind_port.clone()
|
||||||
}
|
))
|
||||||
/// Starts the SSLRelay connection handling.
|
.unwrap();
|
||||||
pub fn start(&mut self) {
|
|
||||||
|
|
||||||
let rhost = self.config.remote_host.clone();
|
let mut conn_id = 0;
|
||||||
let rport = self.config.remote_port.clone();
|
match self.config.downstream_data_type {
|
||||||
let upstream_data_stream_type = self.config.upstream_data_type;
|
TCPDataType::TLS => {
|
||||||
|
let acceptor = self.setup_ssl_config(&self.config.tls_config);
|
||||||
|
|
||||||
let listener = TcpListener::bind(format!("{}:{}", self.config.bind_host.clone(), self.config.bind_port.clone())).unwrap();
|
for stream in listener.incoming() {
|
||||||
|
match stream {
|
||||||
|
Ok(stream) => {
|
||||||
|
let acceptor = acceptor.clone();
|
||||||
|
let mut handler_clone = self.handlers.as_ref().unwrap().clone();
|
||||||
|
|
||||||
match self.config.downstream_data_type {
|
let r_host = rhost.clone();
|
||||||
|
let r_port = rport.clone();
|
||||||
|
|
||||||
TCPDataType::TLS => {
|
let this_conn_id = conn_id;
|
||||||
|
thread::spawn(move || {
|
||||||
|
match acceptor.accept(stream) {
|
||||||
|
Ok(stream) => {
|
||||||
|
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);
|
||||||
|
|
||||||
let acceptor = self.setup_ssl_config(self.config.tls_config.clone());
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
conn_id += 1;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("[Error] Tcp Connection Failed: {}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for stream in listener.incoming() {
|
TCPDataType::RAW => {
|
||||||
|
for stream in listener.incoming() {
|
||||||
|
match stream {
|
||||||
|
Ok(stream) => {
|
||||||
|
let handler_clone = self.handlers.as_ref().unwrap().clone();
|
||||||
|
|
||||||
match stream {
|
let r_host = rhost.clone();
|
||||||
Ok(stream) => {
|
let r_port = rport.clone();
|
||||||
|
|
||||||
let acceptor = acceptor.clone();
|
let this_conn_id = conn_id;
|
||||||
let handler_clone = self.handlers.as_ref().unwrap().clone();
|
thread::spawn(move || {
|
||||||
|
// FULL DUPLEX OBJECT CREATION HERE
|
||||||
|
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
|
||||||
|
),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
conn_id += 1;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("[Error] Tcp Connection Failed: {}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let r_host = rhost.clone();
|
fn setup_ssl_config(&self, tls_config: &TLSConfig) -> Arc<SslAcceptor> {
|
||||||
let r_port = rport.clone();
|
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."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Arc::new(acceptor.build())
|
||||||
|
}
|
||||||
|
|
||||||
thread::spawn(move || {
|
// 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
|
||||||
|
|
||||||
match acceptor.accept(stream) {
|
// struct AcceptorDb {
|
||||||
Ok(stream) => {
|
// acceptors: HashMap<String, Arc<SslAcceptor>>,
|
||||||
// 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) => {
|
|
||||||
|
|
||||||
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) => println!("[SSLRelay Error] Failed to handle TCP connection: {}", _ec),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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} => {
|
|
||||||
|
|
||||||
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.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Arc::new(acceptor.build())
|
|
||||||
}
|
|
||||||
}// SSLRelay
|
|
||||||
|
|
|
||||||
579
src/tcp.rs
579
src/tcp.rs
|
|
@ -1,259 +1,368 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
FullDuplexTcp,
|
mpsc, thread, Arc, CallbackRet, DataPipe, DataStreamType, DownStreamInner, Duration,
|
||||||
HandlerCallbacks,
|
FullDuplexTcp, FullDuplexTcpState, HandlerCallbacks, InnerHandlers, Mutex, Receiver, Sender,
|
||||||
DataStreamType,
|
Shutdown, SslConnector, SslMethod, SslVerifyMode, TCPDataType, TcpStream, UpStreamInner,
|
||||||
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> {
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(ds_tcp_stream: DataStreamType, us_tcp_stream_type: TCPDataType, remote_host: String, remote_port: String, handlers: InnerHandlers<H>) -> Result<Self, i8> {
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match ds_tcp_stream {
|
Ok(FullDuplexTcp {
|
||||||
DataStreamType::RAW(ref s) => { let _ = s.set_read_timeout(Some(Duration::from_millis(50))); },
|
remote_host,
|
||||||
DataStreamType::TLS(ref s) => { let _ = s.get_ref().set_read_timeout(Some(Duration::from_millis(50))); },
|
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,
|
||||||
|
conn_id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let us_tcp_stream = match Self::connect_endpoint(us_tcp_stream_type, remote_host.clone(), remote_port.clone()) {
|
pub fn handle(&mut self) {
|
||||||
Ok(s) => s,
|
let conn_id = self.conn_id;
|
||||||
Err(ec) => {
|
let (state_sender, state_receiver): (
|
||||||
match ds_tcp_stream {
|
Sender<FullDuplexTcpState>,
|
||||||
DataStreamType::RAW(s) => { let _ = s.shutdown(Shutdown::Both); },
|
Receiver<FullDuplexTcpState>,
|
||||||
DataStreamType::TLS(mut s) => { let _ = s.shutdown(); },
|
) = mpsc::channel();
|
||||||
}
|
let (ds_data_pipe_sender, ds_data_pipe_receiver): (Sender<DataPipe>, Receiver<DataPipe>) =
|
||||||
return Err(ec);
|
mpsc::channel();
|
||||||
}
|
let (us_data_pipe_sender, us_data_pipe_receiver): (Sender<DataPipe>, Receiver<DataPipe>) =
|
||||||
};
|
mpsc::channel();
|
||||||
|
|
||||||
Ok(
|
let ds_method_pointer = self.ds_inner_m.clone();
|
||||||
FullDuplexTcp {
|
let ds_state_bc = state_sender.clone();
|
||||||
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 us_method_pointer = self.us_inner_m.clone();
|
||||||
|
let us_state_bc = state_sender.clone();
|
||||||
|
|
||||||
let (state_sender, state_receiver): (Sender<FullDuplexTcpState>, Receiver<FullDuplexTcpState>) = mpsc::channel();
|
thread::spawn(move || {
|
||||||
let (ds_data_pipe_sender, ds_data_pipe_receiver): (Sender<DataPipe>, Receiver<DataPipe>) = mpsc::channel();
|
ds_method_pointer
|
||||||
let (us_data_pipe_sender, us_data_pipe_receiver): (Sender<DataPipe>, Receiver<DataPipe>) = mpsc::channel();
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.take()
|
||||||
|
.unwrap()
|
||||||
|
.ds_handler(ds_state_bc, ds_data_pipe_receiver);
|
||||||
|
});
|
||||||
|
|
||||||
let ds_method_pointer = self.ds_inner_m.clone();
|
thread::spawn(move || {
|
||||||
let ds_state_bc = state_sender.clone();
|
us_method_pointer
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.take()
|
||||||
|
.unwrap()
|
||||||
|
.us_handler(us_state_bc, us_data_pipe_receiver);
|
||||||
|
});
|
||||||
|
|
||||||
let us_method_pointer = self.us_inner_m.clone();
|
loop {
|
||||||
let us_state_bc = state_sender.clone();
|
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)
|
||||||
|
*/
|
||||||
|
|
||||||
thread::spawn(move || {
|
let inner_handlers_clone = self.inner_handlers.clone();
|
||||||
ds_method_pointer.lock().unwrap().take().unwrap().ds_handler(ds_state_bc, ds_data_pipe_receiver);
|
let in_data = data.clone();
|
||||||
});
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
us_method_pointer.lock().unwrap().take().unwrap().us_handler(us_state_bc, us_data_pipe_receiver);
|
inner_handlers_clone.cb.us_nb_callback(in_data, conn_id);
|
||||||
});
|
});
|
||||||
|
|
||||||
loop {
|
match self.inner_handlers.cb.us_b_callback(data, conn_id) {
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
match state_receiver.recv() {
|
let inner_handlers_clone = self.inner_handlers.clone();
|
||||||
Ok(state_request) => {
|
let in_data = data.clone();
|
||||||
match state_request {
|
|
||||||
|
|
||||||
// DownStream Write Request
|
thread::spawn(move || {
|
||||||
FullDuplexTcpState::DownStreamWrite(data) => {
|
inner_handlers_clone.cb.ds_nb_callback(in_data, conn_id);
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
match self.inner_handlers.cb.ds_b_callback(data, conn_id) {
|
||||||
Callbacks that work with data from UpStream go here
|
CallbackRet::Relay(retdata) => {
|
||||||
Add callback return types for blocking callback subroutines
|
match us_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
||||||
Shutdown - Shutdown TCP connection
|
Ok(()) => {}
|
||||||
Relay - Relay TCP stream
|
Err(e) => {
|
||||||
Spoof - Spoof back to received stream direction
|
Self::handle_error(
|
||||||
Freeze - Freeze data (dont relay and destroy data)
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let inner_handlers_clone = self.inner_handlers.clone();
|
fn connect_endpoint(
|
||||||
let in_data = data.clone();
|
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);
|
||||||
|
|
||||||
thread::spawn(move || {
|
let connector = sslbuilder.build();
|
||||||
inner_handlers_clone.cb.us_nb_callback(in_data);
|
|
||||||
});
|
|
||||||
|
|
||||||
match self.inner_handlers.cb.us_b_callback(data) {
|
let s = match TcpStream::connect(format!("{}:{}", remote_host, remote_port)) {
|
||||||
CallbackRet::Relay(retdata) => {
|
Ok(s) => s,
|
||||||
match ds_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
Err(e) => {
|
||||||
Ok(()) => {},
|
Self::handle_error(
|
||||||
Err(e) => {
|
format!(
|
||||||
Self::handle_error(format!("Failed to send data write to DownStream thread: {}", e).as_str());
|
"Can't connect to remote host: {}\nErr: {}",
|
||||||
return;
|
format!("{}:{}", remote_host, remote_port),
|
||||||
}
|
e
|
||||||
}
|
)
|
||||||
},
|
.as_str(),
|
||||||
CallbackRet::Spoof(retdata) => {
|
);
|
||||||
match us_data_pipe_sender.send(DataPipe::DataWrite(retdata)) {
|
return Result::Err(-1);
|
||||||
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) => {
|
|
||||||
|
|
||||||
/*
|
let s = match connector.connect(remote_host.as_str(), s) {
|
||||||
Callbacks that work with data from DownStream go here
|
Ok(s) => s,
|
||||||
*/
|
Err(e) => {
|
||||||
|
Self::handle_error(
|
||||||
|
format!("Failed to accept TLS/SSL handshake: {}", e).as_str(),
|
||||||
|
);
|
||||||
|
return Result::Err(-2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let inner_handlers_clone = self.inner_handlers.clone();
|
let _ = s
|
||||||
let in_data = data.clone();
|
.get_ref()
|
||||||
|
.set_read_timeout(Some(Duration::from_millis(50)));
|
||||||
|
return Ok(DataStreamType::TLS(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
thread::spawn(move || {
|
fn handle_error(error_description: &str) {
|
||||||
inner_handlers_clone.cb.ds_nb_callback(in_data);
|
println!("[SSLRelay Master Thread Error]: {}", error_description);
|
||||||
});
|
}
|
||||||
|
|
||||||
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