//! ## SSLRelay //! 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. //! These callbacks can R/W the data from a stream(Blocking) or only R the data(Non-Blocking). //!``` //!pub trait HandlerCallbacks { //! fn ds_b_callback(&mut self, _in_data: Vec) -> CallbackRet {CallbackRet::Relay(_in_data)} //! fn ds_nb_callback(&self, _in_data: Vec){} //! fn us_b_callback(&mut self, _in_data: Vec) -> CallbackRet {CallbackRet::Relay(_in_data)} //! fn us_nb_callback(&self, _in_data: Vec){} //!} //!``` //! The blocking callbacks return an enum called CallbackRet with four different variants. //! The variants control the flow of the tcp stream. //!``` //! pub enum CallbackRet { //! Relay(Vec),// Relay data //! Spoof(Vec),// Skip relaying and send data back //! Shutdown,// Shutdown TCP connection //! Freeze,// Dont send data (pretend as if stream never was recieved) //! } //! ``` //! ## Example (basic.rs) //! ``` //! use sslrelay::{self, 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 (Read Only) //! fn ds_nb_callback(&self, _in_data: Vec) { //! println!("[CALLBACK] Down Stream Non Blocking CallBack!"); //! } //! //! // DownStream blocking callback (Read & Write) //! fn ds_b_callback(&mut self, _in_data: Vec) -> CallbackRet { //! println!("[CALLBACK] Down Stream Blocking CallBack!"); //! CallbackRet::Relay(_in_data) //! } //! //! // UpStream non blocking callback (Read Only) //! fn us_nb_callback(&self, _in_data: Vec) { //! println!("[CALLBACK] Up Stream Non Blocking CallBack!"); //! } //! //! // UpStream blocking callback (Read & Write) //! fn us_b_callback(&mut self, _in_data: Vec) -> 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(); //! } //! ``` use openssl::ssl::{ SslVerifyMode, SslConnector, SslAcceptor, SslStream, SslFiletype, SslMethod }; use std::net::{ TcpListener, TcpStream, Shutdown }; use std::sync::{ Arc, Mutex }; use std::{ thread }; use std::{ env, fs, path::Path, time::Duration, }; use std::io::{ self, Read, Write }; use std::sync::mpsc::{ self, Receiver, Sender }; use toml::Value as TValue; mod data; mod tcp; mod relay; #[derive(Debug)] enum FullDuplexTcpState { DownStreamWrite(Vec), UpStreamWrite(Vec), DownStreamShutDown, UpStreamShutDown, } #[derive(Debug)] enum DataPipe { DataWrite(Vec), Shutdown, } enum DataStreamType { RAW(TcpStream), TLS(SslStream), } /// Specifies the upstream or downstream data type (TLS or RAW). #[derive(Copy, Clone)] pub enum TCPDataType { TLS, RAW, } /// The relay configuration type. /// Env: Uses the SSLRELAY_CONFIG environmental variable for the path to the config file. /// Path: Specifies the path to the config file. /// Conf: For passing an instance of the object instead of using a config file. /// Default: Uses ./relay_config.toml config file. pub enum ConfigType { Env, Path(T), Conf(RelayConfig), Default, } /// Relay Config structure for passing into the SSLRelay::new() config parameter. #[derive(Clone)] pub struct RelayConfig { pub downstream_data_type: TCPDataType, pub upstream_data_type: TCPDataType, pub bind_host: String, pub bind_port: String, pub remote_host: String, pub remote_port: String, pub ssl_private_key_path: Option, pub ssl_cert_path: Option, } /// CallbackRet for blocking callback functions #[derive(Debug)] pub enum CallbackRet { Relay(Vec),// Relay data Spoof(Vec),// Skip relaying and send data back Shutdown,// Shutdown TCP connection Freeze,// Dont send data (pretend as if stream never was recieved) } /// Callback functions a user may or may not implement. pub trait HandlerCallbacks { fn ds_b_callback(&mut self, _in_data: Vec) -> CallbackRet {CallbackRet::Relay(_in_data)} fn ds_nb_callback(&self, _in_data: Vec){} fn us_b_callback(&mut self, _in_data: Vec) -> CallbackRet {CallbackRet::Relay(_in_data)} fn us_nb_callback(&self, _in_data: Vec){} } /// The main SSLRelay object. #[derive(Clone)] pub struct SSLRelay where H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static, { config: RelayConfig, handlers: Option>, } #[allow(dead_code)] struct FullDuplexTcp where H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static, { remote_host: String, remote_port: String, ds_inner_m: Arc>>, us_inner_m: Arc>>, inner_handlers: InnerHandlers, } #[derive(Clone)] struct InnerHandlers where H: HandlerCallbacks + std::marker::Sync + std::marker::Send + Clone + 'static, { cb: H } struct DownStreamInner { ds_stream: DataStreamType, internal_data_buffer: Vec, } struct UpStreamInner { us_stream: DataStreamType, internal_data_buffer: Vec }