remove rustls

This commit is contained in:
MeexReay 2025-04-06 03:06:28 +03:00
parent 9689d2815c
commit bb042d0f9d
6 changed files with 36 additions and 188 deletions

View File

@ -4,9 +4,7 @@ version = "0.1.2"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
openssl = { version = "0.10.68", optional = true } openssl = "0.10.68"
rustls = { version = "0.23.21", optional = true }
rustls-pemfile = { version = "2.2.0", optional = true }
serde_yml = "0.0.12" serde_yml = "0.0.12"
log = "0.4.25" log = "0.4.25"
colog = "1.3.0" colog = "1.3.0"
@ -14,8 +12,3 @@ threadpool = "1.8.1"
wildcard_ex = "0.1.2" wildcard_ex = "0.1.2"
websocket = "0.27.1" websocket = "0.27.1"
serde_json = "1.0.136" serde_json = "1.0.136"
[features]
default = ["use-openssl"]
use-openssl = ["dep:openssl"]
use-rustls = ["dep:rustls", "dep:rustls-pemfile"]

View File

@ -8,9 +8,10 @@ Features:
- Sending IP in header (X-Real-IP) - Sending IP in header (X-Real-IP)
TODO: TODO:
- Rustls support
- Remove panics - Remove panics
- Creating trees of flowgate - Creating trees of flowgate
- Filter by headers
- Modify response headers
## IP forwarding types ## IP forwarding types
@ -27,10 +28,6 @@ TODO:
You need [Rust](https://www.rust-lang.org/) installed with cargo! You need [Rust](https://www.rust-lang.org/) installed with cargo!
Rust features:
- use-openssl
- use-rustls ([rustls](https://github.com/rustls/rustls) - openssl alternative)
```sh ```sh
cargo run # --------------------------------- # Run cargo run # --------------------------------- # Run
cargo run --release # ----------------------- # Run release cargo run --release # ----------------------- # Run release

View File

@ -1,5 +1,4 @@
pub mod config; pub mod config;
pub mod server; pub mod server;
pub mod ssl_cert; pub mod ssl_cert;
pub mod closeable;
pub mod websocket; pub mod websocket;

View File

@ -1,21 +0,0 @@
use std::net::{Shutdown, TcpStream};
#[cfg(feature = "use-openssl")]
use openssl::ssl::SslStream;
pub trait Closeable {
fn close(&self);
}
impl Closeable for TcpStream {
fn close(&self) {
let _ = self.shutdown(Shutdown::Both);
}
}
#[cfg(feature = "use-openssl")]
impl<T: Closeable> Closeable for SslStream<T> {
fn close(&self) {
self.get_ref().close();
}
}

View File

@ -3,14 +3,31 @@ use std::{
}; };
use log::info; use log::info;
use openssl::ssl::SslStream;
use threadpool::ThreadPool; use threadpool::ThreadPool;
use super::{closeable::Closeable, config::{Config,SiteConfig,IpForwarding}}; use super::config::{Config,SiteConfig,IpForwarding};
pub struct FlowgateServer { pub struct FlowgateServer {
config: Arc<RwLock<Config>>, config: Arc<RwLock<Config>>,
} }
pub trait Closeable {
fn close(&mut self);
}
impl Closeable for SslStream<TcpStream> {
fn close(&mut self) {
let _ = self.shutdown();
}
}
impl Closeable for TcpStream {
fn close(&mut self) {
let _ = self.shutdown(std::net::Shutdown::Both);
}
}
struct Connection { struct Connection {
stream: TcpStream, stream: TcpStream,
config: SiteConfig, config: SiteConfig,
@ -24,30 +41,34 @@ impl FlowgateServer {
} }
pub fn start(&self) { pub fn start(&self) {
let pool = ThreadPool::new(self.config.read().unwrap().threadpool_size);
let pool = Arc::new(pool);
thread::spawn({ thread::spawn({
let config = Arc::clone(&self.config); let config = Arc::clone(&self.config);
let pool = Arc::clone(&pool);
move || { move || {
Self::run_http(config) Self::run_http(config, pool)
} }
}); });
thread::spawn({ thread::spawn({
let config = Arc::clone(&self.config); let config = Arc::clone(&self.config);
let pool = Arc::clone(&pool);
move || { move || {
Self::run_https(config) Self::run_https(config, pool)
} }
}); });
} }
pub fn run_http( pub fn run_http(
config: Arc<RwLock<Config>> config: Arc<RwLock<Config>>,
pool: Arc<ThreadPool>
) -> Option<()> { ) -> Option<()> {
let listener = TcpListener::bind(&config.read().ok()?.http_host).ok()?; let listener = TcpListener::bind(&config.read().ok()?.http_host).ok()?;
let pool = ThreadPool::new(10);
info!("HTTP server runned on {}", &config.read().ok()?.http_host); info!("HTTP server runned on {}", &config.read().ok()?.http_host);
for stream in listener.incoming() { for stream in listener.incoming() {
@ -75,9 +96,9 @@ impl FlowgateServer {
Some(()) Some(())
} }
#[cfg(feature = "use-openssl")]
pub fn run_https( pub fn run_https(
config: Arc<RwLock<Config>> config: Arc<RwLock<Config>>,
pool: Arc<ThreadPool>
) -> Option<()> { ) -> Option<()> {
use openssl::ssl::{NameType, SniError, SslAcceptor, SslAlert, SslMethod, SslRef}; use openssl::ssl::{NameType, SniError, SslAcceptor, SslAlert, SslMethod, SslRef};
@ -99,8 +120,6 @@ impl FlowgateServer {
let cert = cert.build(); let cert = cert.build();
let pool = ThreadPool::new(config.read().ok()?.threadpool_size);
info!("HTTPS server runned on {}", &config.read().ok()?.https_host); info!("HTTPS server runned on {}", &config.read().ok()?.https_host);
for stream in listener.incoming() { for stream in listener.incoming() {
@ -131,62 +150,6 @@ impl FlowgateServer {
Some(()) Some(())
} }
#[cfg(feature = "use-rustls")]
pub fn run_https(
config: Arc<RwLock<Config>>
) -> Option<()> {
use std::sync::Arc;
use rustls::{server::ResolvesServerCertUsingSni, ServerConfig};
use super::ssl_cert::AdoptedConnection;
let listener = TcpListener::bind(&config.https_host).ok()?;
let mut cert_resolver = ResolvesServerCertUsingSni::new();
for site in config.sites.iter() {
if let Some(cert) = site.ssl {
cert_resolver.add(&site.domain, cert.get_certified_key());
}
}
let mut tls_config = Arc::new(
ServerConfig::builder()
.with_no_client_auth()
.with_cert_resolver(Arc::new(cert_resolver))
);
let pool = ThreadPool::new(10);
info!("HTTPS server runned on {}", &config.https_host);
for stream in listener.incoming() {
pool.execute({
let config = config.clone();
let tls_config = tls_config.clone();
move || {
let Ok(mut stream) = stream else { return };
let Ok(_) = stream.set_write_timeout(Some(Duration::from_secs(10))) else { return };
let Ok(_) = stream.set_read_timeout(Some(Duration::from_secs(10))) else { return };
let Ok(addr) = stream.peer_addr() else { return };
let Some(mut stream) = AdoptedConnection::from_config(tls_config, stream) else { return };
Self::accept_stream(
config,
&mut stream,
addr,
true
);
}
});
}
Some(())
}
pub fn accept_stream( pub fn accept_stream(
config: Arc<RwLock<Config>>, config: Arc<RwLock<Config>>,
stream: &mut (impl Read + Write + Closeable), stream: &mut (impl Read + Write + Closeable),
@ -211,9 +174,9 @@ impl FlowgateServer {
Some(()) Some(())
} }
fn read_request<'a>( fn read_request(
config: Arc<RwLock<Config>>, config: Arc<RwLock<Config>>,
stream: &'a mut (impl Read + Write + Closeable), stream: &mut (impl Read + Write + Closeable),
addr: SocketAddr, addr: SocketAddr,
https: bool, https: bool,
conn: Option<Connection> conn: Option<Connection>

View File

@ -1,13 +1,10 @@
#[cfg(feature = "use-openssl")]
use openssl::ssl::SslContext; use openssl::ssl::SslContext;
#[cfg(feature = "use-openssl")]
#[derive(Clone)] #[derive(Clone)]
pub struct SslCert { pub struct SslCert {
context: SslContext, context: SslContext,
} }
#[cfg(feature = "use-openssl")]
fn generate_ctx(cert_file: &str, key_file: &str) -> Option<SslContext> { fn generate_ctx(cert_file: &str, key_file: &str) -> Option<SslContext> {
use openssl::ssl::{SslFiletype, SslMethod}; use openssl::ssl::{SslFiletype, SslMethod};
@ -18,7 +15,6 @@ fn generate_ctx(cert_file: &str, key_file: &str) -> Option<SslContext> {
Some(ctx.build()) Some(ctx.build())
} }
#[cfg(feature = "use-openssl")]
impl SslCert { impl SslCert {
pub fn new(cert_file: &str, key_file: &str) -> Option<SslCert> { pub fn new(cert_file: &str, key_file: &str) -> Option<SslCert> {
Some(SslCert { Some(SslCert {
@ -30,82 +26,3 @@ impl SslCert {
self.context.clone() self.context.clone()
} }
} }
#[cfg(feature = "use-rustls")]
use rustls::{sign::CertifiedKey, server::Acceptor, ServerConfig, ServerConnection};
#[cfg(feature = "use-rustls")]
use std::{net::TcpStream, sync::Arc};
#[cfg(feature = "use-rustls")]
#[derive(Clone)]
pub struct SslCert {
cert_key: CertifiedKey,
}
#[cfg(feature = "use-rustls")]
fn generate_cert_key(cert_file: &str, key_file: &str) -> Option<CertifiedKey> {
use rustls::crypto::CryptoProvider;
use std::fs::File;
use std::io::BufReader;
let key = rustls_pemfile::private_key(&mut BufReader::new(File::open(key_file).ok()?)).ok()??;
let key = CryptoProvider::get_default().unwrap().key_provider.load_private_key(key).ok()?;
let cert =
rustls_pemfile::public_keys(&mut BufReader::new(File::open(cert_file).ok()?))
.map(|o| o.unwrap().to_vec().into())
.collect::<Vec<_>>();
Some(CertifiedKey::new(cert, key))
}
#[cfg(feature = "use-rustls")]
impl SslCert {
pub fn new(cert_file: &str, key_file: &str) -> Option<SslCert> {
Some(SslCert {
cert_key: generate_cert_key(cert_file, key_file)?,
})
}
pub fn get_certified_key(&self) -> CertifiedKey {
self.cert_key.clone()
}
}
#[cfg(feature = "use-rustls")]
pub struct AdoptedConnection {
server_connection: ServerConnection,
stream: TcpStream
}
#[cfg(feature = "use-rustls")]
impl AdoptedConnection {
pub fn new(
server_connection: ServerConnection,
stream: TcpStream
) -> AdoptedConnection {
AdoptedConnection {
server_connection,
stream
}
}
pub fn from_config(
server_config: Arc<ServerConfig>,
mut stream: TcpStream
) -> Option<AdoptedConnection> {
let mut acceptor = Acceptor::default();
let accepted = loop {
acceptor.read_tls(&mut stream).ok()?;
if let Some(accepted) = acceptor.accept().ok()? {
break accepted;
}
};
Some(AdoptedConnection {
server_connection: accepted.into_connection(server_config).ok()?,
stream
})
}
}
// TODO: implement Read and Write and Closeable to AdoptedConnection