Compare commits

...

10 commits

Author SHA1 Message Date
ZettaScript
6828beeb52 Fmt, add experimental features 2025-10-30 11:54:08 +01:00
PinkP4nther
0e9b4feaf7 Version 0.6.2 2021-10-10 00:53:50 -07:00
PinkP4nther
b5ef3263c6 Warnings gone 2021-10-10 00:51:30 -07:00
PinkP4nther
1b2ed7a10d Silenced channel send error for StreamWrite's to master thread. If client disconnects before server send response the relay will now just silently close the connection. 2021-10-10 00:48:53 -07:00
PinkP4nther
fea7a127b4 Add to network programming category 2021-10-09 22:29:05 -07:00
PinkP4nther
61217ed351 New configuration method. Version 0.6.0. Examples updated to new configuration method. Configuration files removed. 2021-10-09 22:05:03 -07:00
PinkP4nther
32645a48c3 No longer need process import 2021-10-08 22:08:39 -07:00
PinkP4nther
edb41aaf54 V 5 2021-10-08 22:06:57 -07:00
PinkP4nther
2691138ee5 V 5 No changes 2021-10-08 22:05:27 -07:00
PinkP4nther
cc8198aaf6 Fix README typo 2021-10-08 21:47:16 -07:00
13 changed files with 1125 additions and 1057 deletions

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"rust-analyzer.showUnlinkedFileNotification": false
}

View file

@ -1,16 +1,13 @@
[package] [package]
name = "sslrelay" name = "sslrelay"
version = "0.4.4" version = "0.6.2"
authors = ["PinkP4nther <pinkp4nther@protonmail.com> @Pink_P4nther"] authors = ["PinkP4nther <pinkp4nther@protonmail.com> @Pink_P4nther"]
edition = "2018" edition = "2018"
description = "A TCP relay library for relaying/modifying/spoofing TCP traffic by implementing callback code." description = "A TCP relay library for relaying/modifying/spoofing TCP traffic by implementing callback code."
repository = "https://github.com/PinkP4nther/SSLRelay-lib" repository = "https://github.com/PinkP4nther/SSLRelay-lib"
keywords = ["tcp", "networking", "relay", "tls", "ssl"] keywords = ["tcp", "networking", "relay", "tls", "ssl"]
categories = ["reverse-engineering", "network-relay", "tcp"] categories = ["network-programming"]
license = "Apache-2.0" license = "Apache-2.0"
[dependencies.openssl] [dependencies.openssl]
version = "0.10.36" version = "0.10.36"
[dependencies.toml]
version = "0.5.8"

View file

@ -28,4 +28,10 @@ A TCP relay library that can handle raw TCP and SSL/TLS connections. You can rea
> 10/06/2021 | **v0.4.2** | Added documentation. > 10/06/2021 | **v0.4.2** | Added documentation.
> >
> 10/07/2021 | **v0.4.3** | Blocking callbacks now pass self as a mutable reference. This can allow the developer to create structures that can be accessed every stream write. (ONLY in the BLOCKING callback). The self object is refreshed per TCP connection. Separate TCP connections can not touch eachothers data. > 10/07/2021 | **v0.4.3** | Blocking callbacks now pass self as a mutable reference. This can allow the developer to create structures that can be accessed every stream write. (ONLY in the BLOCKING callback). The self object is refreshed per TCP connection. Separate TCP connections can not touch eachothers data.
>
> 10/08/2021 | **v0.4.4** | Added ability to set TLS certificate and certificate private key to nothing. When passing RelayConfig to the relay object use the 'None' variant of Option<T> enum. In a config file put the cert path and key path as an empty 'String' to specify 'None'. > 10/08/2021 | **v0.4.4** | Added ability to set TLS certificate and certificate private key to nothing. When passing RelayConfig to the relay object use the 'None' variant of Option<T> enum. In a config file put the cert path and key path as an empty 'String' to specify 'None'.
>
> 10/09/2021 | **v0.6.0** | Gone away with 'ConfigType<T>'! No more specifying config files unless the developer implements it themself. A new config enum 'TLSConfig' has been introduced. This has 3 variants FILE(Specify the cert and pk file paths), DATA(Pass the cert(PEM) data and the pk(PEM) data as bytes), NONE(This is when you are not using TLS on the listening/downstream side of the relay).
>
> 10/10/2021 | **v0.6.2** | StreamWrite's to master thread are no longer verbose when the opposite stream disconnects randomly.
>

66
examples/basic.rs Normal file
View 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();
}

View file

@ -1,54 +0,0 @@
use sslrelay::{self, ConfigType, RelayConfig, HandlerCallbacks, CallbackRet, TCPDataType};
// 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,
ConfigType::Conf(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(),
ssl_private_key_path: Some("./remote.com.key".to_string()),
ssl_cert_path: Some("./remote.com.crt".to_string()),
})
);
// Start listening
relay.start();
}

View file

@ -1,8 +0,0 @@
bind_host = "0.0.0.0"
bind_port = "443"
ssl_private_key_path = "./remote.com.key"
ssl_cert_path = "./remote.com.crt"
remote_host = "remote.com"
remote_port = "443"
downstream_data_type = "tls"
upstream_data_type = "tls"

View file

@ -1,4 +1,4 @@
use sslrelay::{self, ConfigType, HandlerCallbacks, CallbackRet}; use sslrelay::{self, TLSConfig, TCPDataType, RelayConfig, HandlerCallbacks, CallbackRet};
// Handler object // Handler object
#[derive(Clone)] // Must have Clone trait implemented. #[derive(Clone)] // Must have Clone trait implemented.
@ -38,7 +38,21 @@ impl HandlerCallbacks for Handler {
fn main() { fn main() {
// Create new SSLRelay object // Create new SSLRelay object
let mut relay = sslrelay::SSLRelay::new(Handler, ConfigType::Default); 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 // Start listening
relay.start(); relay.start();

View file

@ -1,8 +0,0 @@
bind_host = "0.0.0.0"
bind_port = "443"
ssl_private_key_path = "./ssl.key"
ssl_cert_path = "./ssl.crt"
remote_host = "remote.com"
remote_port = "443"
downstream_data_type = "tls"
upstream_data_type = "tls"

8
rustfmt.toml Normal file
View 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

View file

@ -1,434 +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());
return;
}
self.internal_data_buffer.clear(); let _bw = internal_data_buffer
.write(r_buf.split_at(bytes_read).0)
} else if byte_count == 0 || byte_count == -2 { .unwrap();
data_length += bytes_read as i64;
let _ = data_out.send(FullDuplexTcpState::DownStreamShutDown); } else {
let _ = raw_stream.shutdown(Shutdown::Both); println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
return; }
}
} else if byte_count == -1 { Err(e) => match e.kind() {
continue; io::ErrorKind::WouldBlock => {
} if data_length == 0 {
} else { data_length = -1;
}
} break;
} }
} io::ErrorKind::ConnectionReset => {
data_length = -2;
fn handle_tls(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) { break;
}
let mut tls_stream = match self.ds_stream { _ => {
DataStreamType::TLS(ref mut s) => s, println!("[!!!downstream] Got error: {}", e);
_ => return, }
}; },
}
loop { }
return Some(data_length);
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());
return;
}
self.internal_data_buffer.clear(); let _bw = internal_data_buffer
.write(r_buf.split_at(bytes_read).0)
} else if byte_count == 0 || byte_count == -2 { .unwrap();
data_length += bytes_read as i64;
let _ = data_out.send(FullDuplexTcpState::UpStreamShutDown); } else {
let _ = raw_stream.shutdown(Shutdown::Both); println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
return; }
} else if byte_count == -1 { }
continue; Err(e) => match e.kind() {
} io::ErrorKind::WouldBlock => {
} else { if data_length == 0 {
} data_length = -1;
} }
} break;
}
fn handle_tls(mut self, data_out: Sender<FullDuplexTcpState>, data_in: Receiver<DataPipe>) { io::ErrorKind::ConnectionReset => {
data_length = -2;
let mut tls_stream = match self.us_stream { break;
DataStreamType::TLS(ref mut s) => s, }
_ => return, _ => {
}; println!("[!!!upstream] Got error: {}", e);
}
loop { },
}
match data_in.recv_timeout(Duration::from_millis(50)) { }
return Some(data_length);
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());
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);
}
} }

View file

@ -1,240 +1,226 @@
//! ## SSLRelay //! ## SSLRelay
//! Library for relaying TCP traffic as well as TLS encrypted TCP traffic. //! Library for relaying TCP traffic as well as TLS encrypted TCP traffic.
//! 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, ConfigType, RelayConfig, HandlerCallbacks, CallbackRet, TCPDataType}; //! 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,
//! ConfigType::Conf(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(),
//! ssl_private_key_path: Some("./remote.com.key".to_string()),
//! ssl_cert_path: Some("./remote.com.crt".to_string()),
//! })
//! );
//! // Start listening
//! relay.start();
//! } //! }
//! ``` //! ```
use openssl::ssl::{ use openssl::{
SslVerifyMode, pkey::PKey,
SslConnector, ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslStream, SslVerifyMode},
SslAcceptor, x509::X509,
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;
process,
thread
};
use std::{ use std::{path::Path, time::Duration};
env,
fs,
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
};
use toml::Value as TValue;
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,
} }
/// The relay configuration type. /// TLSConfig is used to specify TLS options.
/// Env: Uses the SSLRELAY_CONFIG environmental variable for the path to the config file. /// FILE is for specifying a path to a certificate and private key.
/// Path: Specifies the path to the config file. /// DATA is for passing the certificate and private key bytes directly.
/// Conf: For passing an instance of the object instead of using a config file. /// NONE is for when you are not using TLS on the listening/downstream side of the relay.
/// Default: Uses ./relay_config.toml config file. #[derive(Clone)]
pub enum ConfigType<T> { pub enum TLSConfig {
Env, FILE {
Path(T), certificate_path: String,
Conf(RelayConfig), private_key_path: String,
Default, },
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 ssl_private_key_path: Option<String>, pub remote_port: String,
pub ssl_cert_path: Option<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>
} }

View file

@ -1,208 +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,
ConfigType,
TcpListener,
thread,
FullDuplexTcp,
DataStreamType,
RelayConfig,
env,
TValue,
fs,
process,
Arc,
SslAcceptor,
Path,
SslMethod,
SslFiletype,
}; };
impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static> SSLRelay<H> { 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: ConfigType<String>) -> 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: Self::load_relay_config(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 listener = TcpListener::bind(format!("{}:{}", self.config.bind_host.clone(), self.config.bind_port.clone())).unwrap(); TCPDataType::TLS => {
let upstream_data_stream_type = self.config.upstream_data_type; let acceptor = self.setup_ssl_config(&self.config.tls_config);
match self.config.downstream_data_type { for stream in listener.incoming() {
match stream {
Ok(stream) => {
let acceptor = acceptor.clone();
let mut handler_clone = self.handlers.as_ref().unwrap().clone();
TCPDataType::TLS => { let r_host = rhost.clone();
let acceptor = self.setup_ssl_config(self.config.ssl_private_key_path.clone(), self.config.ssl_cert_path.clone()); let r_port = rport.clone();
for stream in listener.incoming() { 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);
match stream { // FULL DUPLEX OBJECT CREATION HERE
Ok(stream) => { 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)
}
}
}
}
let acceptor = acceptor.clone(); TCPDataType::RAW => {
let handler_clone = self.handlers.as_ref().unwrap().clone(); 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_host = rhost.clone();
let r_port = rport.clone(); let r_port = rport.clone();
thread::spawn(move || { 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)(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)
}
}
}
}
}
}
match acceptor.accept(stream) { fn setup_ssl_config(&self, tls_config: &TLSConfig) -> Arc<SslAcceptor> {
Ok(stream) => { let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
// FULL DUPLEX OBJECT CREATION HERE match tls_config {
match FullDuplexTcp::new(DataStreamType::TLS(stream), upstream_data_stream_type, r_host, r_port, handler_clone) { TLSConfig::FILE {
Ok(mut fdtcp) => fdtcp.handle(), certificate_path,
Err(_ec) => {} private_key_path,
} } => {
}, if !Path::new(&private_key_path).exists() {
Err(e) => { 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())
}
println!("[Error] {}", e); // 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 {
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)} // 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
TCPDataType::RAW => { // struct AcceptorDb {
// acceptors: HashMap<String, Arc<SslAcceptor>>,
for stream in listener.incoming() { // }
match stream {
Ok(stream) => {
let handler_clone = self.handlers.as_ref().unwrap().clone();
let r_host = rhost.clone();
let r_port = rport.clone();
thread::spawn(move || {
// FULL DUPLEX OBJECT CREATION HERE
match FullDuplexTcp::new(DataStreamType::RAW(stream), upstream_data_stream_type, r_host, r_port, handler_clone) {
Ok(mut fdtcp) => fdtcp.handle(),
Err(_ec) => {},
}
});
},
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)}
}
}
}
}
}
fn load_relay_config(config: ConfigType<String>) -> RelayConfig {
let mut resolved_path = String::from("./relay_config.toml");
match config {
ConfigType::Path(path) => {
resolved_path = path.clone();
},
ConfigType::Env => {
resolved_path = match env::var("SSLRELAY_CONFIG") {
Ok(p) => p.clone(),
Err(_e) => {
println!("[-] Environmental variable SSLRELAY_CONFIG does not exist.");
std::process::exit(-1);
}
};
},
ConfigType::Conf(conf) => {
return conf;
}
ConfigType::Default => {}
}
let bytes = fs::read(resolved_path).unwrap();
let config_file = String::from_utf8_lossy(&bytes);
let config_parsed = config_file.parse::<TValue>().unwrap();
let bind_host = config_parsed["bind_host"].to_string().replace("\"", "");
let bind_port = config_parsed["bind_port"].to_string().replace("\"", "");
let ssl_private_key_path = config_parsed["ssl_private_key_path"].to_string().replace("\"", "");
let ssl_cert_path = config_parsed["ssl_cert_path"].to_string().replace("\"", "");
let remote_host = config_parsed["remote_host"].to_string().replace("\"", "");
let remote_port = config_parsed["remote_port"].to_string().replace("\"", "");
let upstream_tls_conf = config_parsed["upstream_data_type"].to_string().replace("\"", "").to_lowercase();
let downstream_tls_conf = config_parsed["downstream_data_type"].to_string().replace("\"", "").to_lowercase();
let upstream_data_type: TCPDataType;
let downstream_data_type: TCPDataType;
if upstream_tls_conf == "tls" {
upstream_data_type = TCPDataType::TLS;
} else if upstream_tls_conf == "raw" {
upstream_data_type = TCPDataType::RAW;
} else {
panic!("[SSLRelay Error] Unrecognized TCPDataType for upstream_data_type. Data type received was not 'tcp' or 'tls'!");
// Create error handling for load_relay_config()
}
if downstream_tls_conf == "tls" {
downstream_data_type = TCPDataType::TLS;
} else if downstream_tls_conf == "raw" {
downstream_data_type = TCPDataType::RAW;
} else {
panic!("[SSLRelay Error] Unrecognized TCPDataType for downstream_data_type. Data type received was not 'tcp' or 'tls'!");
// Create error handling for load_relay_config()
}
let mut ssl_pk_path = None;
let mut ssl_c_path = None;
if !ssl_private_key_path.is_empty() {
ssl_pk_path = Some(ssl_private_key_path.clone());
}
if !ssl_cert_path.is_empty() {
ssl_c_path = Some(ssl_cert_path.clone());
}
RelayConfig {
upstream_data_type,
downstream_data_type,
bind_host: bind_host.clone(),
bind_port: bind_port.clone(),
ssl_private_key_path: ssl_pk_path,
ssl_cert_path: ssl_c_path,
remote_host: remote_host.clone(),
remote_port: remote_port.clone(),
}
}
fn setup_ssl_config(&self, priv_key: Option<String>, cert: Option<String>) -> Arc<SslAcceptor> {
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
let private_key = priv_key.expect("[SSLRelay Error] No private key file specified!");
let certificate = cert.expect("[SSLRelay Error] No certificate file specified!");
if !Path::new(&private_key).exists() {
panic!("[-] [{}] does not exist!", private_key);
}
acceptor.set_private_key_file(private_key, SslFiletype::PEM).unwrap();
if !Path::new(&certificate).exists() {
panic!("[-] [{}] does not exist!", certificate);
}
acceptor.set_certificate_chain_file(certificate).unwrap();
acceptor.check_private_key().unwrap();
Arc::new(acceptor.build())
}
}// SSLRelay

View file

@ -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);
}
} }