temp
This commit is contained in:
parent
985b1d3810
commit
7757ef32f4
5 changed files with 796 additions and 30 deletions
701
Cargo.lock
generated
701
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -25,4 +25,9 @@ ansi_colours = "1.2.3"
|
||||||
colour = "2.1.0"
|
colour = "2.1.0"
|
||||||
async-trait = "0.1.88"
|
async-trait = "0.1.88"
|
||||||
http = "1.3.1"
|
http = "1.3.1"
|
||||||
|
instant-acme = "0.8.2"
|
||||||
|
rustls = "0.23.31"
|
||||||
|
safe-path = "0.1.0"
|
||||||
|
rustls-pemfile = "2.2.0"
|
||||||
|
tokio-rustls = "0.26.2"
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ mod matchers;
|
||||||
mod routes;
|
mod routes;
|
||||||
mod server;
|
mod server;
|
||||||
mod services;
|
mod services;
|
||||||
|
mod tls;
|
||||||
|
|
||||||
use std::{env, process::exit, sync::Arc, time::Duration};
|
use std::{env, process::exit, sync::Arc, time::Duration};
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ use log::{debug, error, info};
|
||||||
use matchers::api::ApiMatcher;
|
use matchers::api::ApiMatcher;
|
||||||
use server::Server;
|
use server::Server;
|
||||||
use services::{controller::ControllerService, matcher::Matcher};
|
use services::{controller::ControllerService, matcher::Matcher};
|
||||||
|
use tls::TlsOption;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
sync::Mutex,
|
sync::Mutex,
|
||||||
time::{self},
|
time::{self},
|
||||||
|
@ -81,11 +83,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
database: database_shared.clone(),
|
database: database_shared.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let api_server = Server::new(api_matcher.service(), (config.api.listen, config.api.port))
|
let api_server = Server::new(api_matcher.service(), (config.api.listen, config.api.port), TlsOption::NoTls)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let proxy_server = Server::new(svc, (config.proxy.listen, config.proxy.port))
|
let proxy_server = Server::new(svc, (config.proxy.listen, config.proxy.port), TlsOption::NoTls)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
use std::{any::type_name_of_val, error::Error};
|
use std::{any::type_name_of_val, collections::HashMap, error::Error, sync::Arc};
|
||||||
|
|
||||||
use http_body_util::{Either, Full};
|
use http_body_util::{Either, Full};
|
||||||
use hyper::{
|
use hyper::{
|
||||||
Request, Response, StatusCode,
|
Request, Response, StatusCode,
|
||||||
body::{Body, Bytes, Incoming},
|
body::{Body, Bytes, Incoming},
|
||||||
|
rt::{Read, Write},
|
||||||
server::conn::http1,
|
server::conn::http1,
|
||||||
service::{HttpService, Service},
|
service::{HttpService, Service},
|
||||||
};
|
};
|
||||||
use hyper_util::rt::TokioIo;
|
use hyper_util::rt::TokioIo;
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
|
use rustls::server::Acceptor;
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tokio_rustls::{LazyConfigAcceptor, StartHandshake};
|
||||||
|
|
||||||
|
use crate::tls::TlsOption;
|
||||||
|
|
||||||
pub type GeneralResponse = Response<GeneralBody>;
|
pub type GeneralResponse = Response<GeneralBody>;
|
||||||
pub type GeneralBody = Either<Incoming, Full<Bytes>>;
|
pub type GeneralBody = Either<Incoming, Full<Bytes>>;
|
||||||
|
@ -23,6 +28,7 @@ pub fn to_general_response(res: Response<Incoming>) -> GeneralResponse {
|
||||||
pub struct Server<S> {
|
pub struct Server<S> {
|
||||||
listener: TcpListener,
|
listener: TcpListener,
|
||||||
service: S,
|
service: S,
|
||||||
|
tls: TlsOption,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TcpIntercept {
|
pub trait TcpIntercept {
|
||||||
|
@ -59,7 +65,7 @@ pub async fn json_to_vec(v: JsonValue) -> Option<Vec<String>> {
|
||||||
|
|
||||||
impl<S> Server<S>
|
impl<S> Server<S>
|
||||||
where
|
where
|
||||||
S: TcpIntercept,
|
S: TcpIntercept + Sync,
|
||||||
S: Service<Request<Incoming>> + Clone + Send + 'static,
|
S: Service<Request<Incoming>> + Clone + Send + 'static,
|
||||||
S: HttpService<Incoming> + Clone + Send,
|
S: HttpService<Incoming> + Clone + Send,
|
||||||
<S::ResBody as Body>::Error: Into<Box<dyn Error + Send + Sync>>,
|
<S::ResBody as Body>::Error: Into<Box<dyn Error + Send + Sync>>,
|
||||||
|
@ -75,31 +81,63 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (stream, _) = self.listener.accept().await.unwrap();
|
let (tcp_stream, _) = self.listener.accept().await.unwrap();
|
||||||
|
|
||||||
let mut svc_clone = self.service.clone();
|
let mut svc_clone = self.service.clone();
|
||||||
svc_clone.stream(&stream);
|
let tls = self.tls.clone();
|
||||||
|
|
||||||
let io = TokioIo::new(stream);
|
|
||||||
|
|
||||||
tokio::task::spawn(async move {
|
tokio::task::spawn(async move {
|
||||||
|
svc_clone.stream(&tcp_stream);
|
||||||
|
|
||||||
|
match tls {
|
||||||
|
TlsOption::NoTls => {
|
||||||
if let Err(err) = http1::Builder::new()
|
if let Err(err) = http1::Builder::new()
|
||||||
.writev(false)
|
.writev(false)
|
||||||
.serve_connection(io, svc_clone)
|
.serve_connection(TokioIo::new(tcp_stream), svc_clone)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
error!("Error while trying to serve connection: {err}")
|
error!("Error while trying to serve connection: {err}")
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
TlsOption::Tls(x) => {
|
||||||
|
let acceptor = LazyConfigAcceptor::new(Acceptor::default(), tcp_stream);
|
||||||
|
|
||||||
|
match acceptor.await {
|
||||||
|
Ok(y) => {
|
||||||
|
let hello = y.client_hello();
|
||||||
|
let hostname = hello.server_name().clone().unwrap();
|
||||||
|
let config = Arc::new(x.matcher(hostname).unwrap());
|
||||||
|
let stream = y
|
||||||
|
.into_stream(config)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if let Err(err) = http1::Builder::new()
|
||||||
|
.writev(false)
|
||||||
|
.serve_connection(TokioIo::new(stream), svc_clone)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
error!("Error while trying to serve connection: {err}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Error while initiating handshake: {e}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new(service: S, a: (String, u16)) -> Result<Self, Box<dyn Error>> {
|
pub async fn new(service: S, a: (String, u16), tls: TlsOption) -> Result<Self, Box<dyn Error>> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
listener: TcpListener::bind(&a).await?,
|
listener: TcpListener::bind(&a).await?,
|
||||||
service,
|
service,
|
||||||
|
tls,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*/
|
*/
|
||||||
|
|
48
src/tls.rs
Normal file
48
src/tls.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
use std::{
|
||||||
|
error::{self, Error},
|
||||||
|
fs::File,
|
||||||
|
io,
|
||||||
|
path::{self, Path},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
|
use rustls::{
|
||||||
|
ServerConfig, crypto,
|
||||||
|
pki_types::{CertificateDer, PrivateKeyDer, pem::PemObject},
|
||||||
|
sign::CertifiedKey,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum TlsOption {
|
||||||
|
NoTls,
|
||||||
|
Tls(FileTls),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct FileTls {
|
||||||
|
pub certs_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileTls {
|
||||||
|
pub fn matcher(&self, hostname: &str) -> Result<ServerConfig, Box<dyn Error>> {
|
||||||
|
let path_to_pem =
|
||||||
|
safe_path::scoped_join(self.certs_path.clone(), format!("{hostname}.pem"))?;
|
||||||
|
let path_to_key =
|
||||||
|
safe_path::scoped_join(self.certs_path.clone(), format!("{hostname}.key"))?;
|
||||||
|
|
||||||
|
let certfile = File::open(path_to_pem)?;
|
||||||
|
let mut cert_reader = io::BufReader::new(certfile);
|
||||||
|
let certs = rustls_pemfile::certs(&mut cert_reader)
|
||||||
|
.map(|x| x.unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let keyfile = File::open(path_to_key)?;
|
||||||
|
let mut key_reader = io::BufReader::new(keyfile);
|
||||||
|
let key = rustls_pemfile::private_key(&mut key_reader).map(|key| key.unwrap())?;
|
||||||
|
|
||||||
|
Ok(ServerConfig::builder()
|
||||||
|
.with_no_client_auth()
|
||||||
|
.with_single_cert(certs, key)
|
||||||
|
.map_err(|e| e)?)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue