trying to ad rustls support
This commit is contained in:
parent
c30cf3fbe9
commit
ffce1a2b80
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -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"
|
||||
|
@ -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"]
|
@ -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),
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user