trying to ad rustls support

This commit is contained in:
MeexReay 2024-09-14 15:01:23 +03:00
parent c30cf3fbe9
commit ffce1a2b80
4 changed files with 171 additions and 14 deletions

17
Cargo.lock generated
View File

@ -93,6 +93,12 @@ dependencies = [
"paste",
]
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bindgen"
version = "0.69.4"
@ -254,6 +260,7 @@ dependencies = [
"log",
"openssl",
"rustls",
"rustls-pemfile",
"serde_yml",
"threadpool",
]
@ -613,6 +620,16 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rustls-pemfile"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425"
dependencies = [
"base64",
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.8.0"

View File

@ -6,12 +6,14 @@ edition = "2021"
[dependencies]
openssl = { version = "0.10.66", optional = true }
rustls = { version = "0.23.13", optional = true }
rustls-pemfile = { version = "2.1.3", optional = true }
serde_yml = "0.0.12"
log = "0.4.22"
colog = "1.3.0"
threadpool = "1.8.1"
[features]
default = ["use-openssl"]
# default = ["use-openssl"]
default = ["use-rustls"]
use-openssl = ["dep:openssl"]
use-rustls = ["dep:rustls"]
use-rustls = ["dep:rustls", "dep:rustls-pemfile"]

View File

@ -1,7 +1,6 @@
use std::{io::{Read, Write}, net::{Shutdown, SocketAddr, TcpListener}, sync::Arc, thread, time::Duration};
use log::info;
use openssl::ssl::{NameType, SniError, SslAcceptor, SslAlert, SslMethod, SslRef};
use threadpool::ThreadPool;
use super::Config;
@ -15,7 +14,7 @@ impl FlowgateServer {
FlowgateServer { config: Arc::new(config) }
}
pub fn start(self) {
pub fn start(&self) {
thread::spawn({
let config = Arc::clone(&self.config);
@ -67,9 +66,12 @@ impl FlowgateServer {
Some(())
}
#[cfg(feature = "use-openssl")]
pub fn run_https(
config: Arc<Config>
) -> Option<()> {
use openssl::ssl::{NameType, SniError, SslAcceptor, SslAlert, SslMethod, SslRef};
let listener = TcpListener::bind(&config.https_host).ok()?;
let mut cert = SslAcceptor::mozilla_intermediate(SslMethod::tls()).ok()?;
@ -119,6 +121,62 @@ impl FlowgateServer {
Some(())
}
#[cfg(feature = "use-rustls")]
pub fn run_https(
config: Arc<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(
config: Arc<Config>,
stream: &mut (impl Read + Write),

View File

@ -1,11 +1,16 @@
use openssl::ssl::{SslContext, SslFiletype, SslMethod};
#[cfg(feature = "use-openssl")]
use openssl::ssl::SslContext;
#[cfg(feature = "use-openssl")]
#[derive(Clone)]
pub struct SslCert {
context: Option<SslContext>,
context: SslContext,
}
#[cfg(feature = "use-openssl")]
fn generate_ctx(cert_file: &str, key_file: &str) -> Option<SslContext> {
use openssl::ssl::{SslFiletype, SslMethod};
let mut ctx = SslContext::builder(SslMethod::tls()).ok()?;
ctx.set_private_key_file(&key_file, SslFiletype::PEM).ok()?;
ctx.set_certificate_file(&cert_file, SslFiletype::PEM).ok()?;
@ -13,19 +18,94 @@ fn generate_ctx(cert_file: &str, key_file: &str) -> Option<SslContext> {
Some(ctx.build())
}
#[cfg(feature = "use-openssl")]
impl SslCert {
pub fn new(cert_file: &str, key_file: &str) -> Option<SslCert> {
Some(SslCert {
context: match generate_ctx(cert_file, key_file) {
Some(i) => Some(i),
None => {
return None;
}
}
context: generate_ctx(cert_file, key_file)?
})
}
pub fn get_context(&self) -> SslContext {
self.context.as_ref().unwrap().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 to AdoptedConnection