//! ## 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, 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 (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, //! 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(), //! }, //! }, //! ); //! //! // Start listening //! relay.start(); //! } //! ``` use openssl::{ pkey::PKey, ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslStream, SslVerifyMode}, x509::X509, }; use std::net::{Shutdown, TcpListener, TcpStream}; use std::sync::{Arc, Mutex}; use std::thread; use std::{path::Path, time::Duration}; use std::io::{self, Read, Write}; use std::sync::mpsc::{self, Receiver, Sender}; mod data; mod relay; mod tcp; #[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, } /// TLSConfig is used to specify TLS options. /// FILE is for specifying a path to a certificate and private key. /// DATA is for passing the certificate and private key bytes directly. /// NONE is for when you are not using TLS on the listening/downstream side of the relay. #[derive(Clone)] pub enum TLSConfig { FILE { certificate_path: String, private_key_path: String, }, DATA { certificate: Vec, private_key: Vec, }, NONE, } /// 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: fn(Option<&str>) -> String, //pub remote_host: String, pub remote_port: String, pub tls_config: TLSConfig, } /// 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, _conn_id: u64) -> CallbackRet { CallbackRet::Relay(_in_data) } fn ds_nb_callback(&self, _in_data: Vec, _conn_id: u64) {} fn us_b_callback(&mut self, _in_data: Vec, _conn_id: u64) -> CallbackRet { CallbackRet::Relay(_in_data) } fn us_nb_callback(&self, _in_data: Vec, _conn_id: u64) {} fn set_server_name(&mut self, _server_name: Option<&str>) {} } /// 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, conn_id: u64, } #[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, }