✨ TLS
This commit is contained in:
@@ -7,5 +7,5 @@ use crate::config::loader::load_settings;
|
||||
pub mod loader;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref C: RwLock<Config> = RwLock::new(load_settings());
|
||||
pub static ref CFG: RwLock<Config> = RwLock::new(load_settings());
|
||||
}
|
||||
|
34
src/main.rs
34
src/main.rs
@@ -2,7 +2,9 @@ mod config;
|
||||
mod proxies;
|
||||
mod sideload;
|
||||
pub mod warden;
|
||||
mod tls;
|
||||
|
||||
use std::error;
|
||||
use actix_web::{App, HttpServer, web};
|
||||
use actix_web::middleware::Logger;
|
||||
use actix_web_httpauth::extractors::AuthenticationError;
|
||||
@@ -20,7 +22,7 @@ lazy_static! {
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), std::io::Error> {
|
||||
async fn main() -> Result<(), Box<dyn error::Error>> {
|
||||
// Setting up logging
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(Level::DEBUG)
|
||||
@@ -29,11 +31,10 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
// Prepare all the stuff
|
||||
info!("Loading proxy regions...");
|
||||
match proxies::loader::scan_regions(
|
||||
config::C
|
||||
config::CFG
|
||||
.read()
|
||||
.await
|
||||
.get_string("regions")
|
||||
.unwrap_or("./regions".to_string()),
|
||||
.get_string("regions")?
|
||||
) {
|
||||
Err(_) => error!("Loading proxy regions... failed"),
|
||||
Ok((regions, count)) => {
|
||||
@@ -48,23 +49,30 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
.wrap(Logger::default())
|
||||
.app_data(web::Data::new(Client::default()))
|
||||
.route("/", web::to(route::handle))
|
||||
}).bind(
|
||||
config::C
|
||||
}).bind_rustls_0_22(
|
||||
config::CFG
|
||||
.read()
|
||||
.await
|
||||
.get_string("listen.proxies")
|
||||
.unwrap_or("0.0.0.0:80".to_string())
|
||||
.get_string("listen.proxies_tls")?,
|
||||
tls::use_rustls().await?,
|
||||
)?.bind(
|
||||
config::CFG
|
||||
.read()
|
||||
.await
|
||||
.get_string("listen.proxies")?
|
||||
)?.run();
|
||||
|
||||
// Sideload
|
||||
let sideload_server = HttpServer::new(|| {
|
||||
App::new()
|
||||
.wrap(HttpAuthentication::basic(|req, credentials| async move {
|
||||
let password = config::C
|
||||
let password = match config::CFG
|
||||
.read()
|
||||
.await
|
||||
.get_string("secret")
|
||||
.unwrap_or("".to_string());
|
||||
.get_string("secret") {
|
||||
Ok(val) => val,
|
||||
Err(_) => return Err((AuthenticationError::new(Basic::new()).into(), req))
|
||||
};
|
||||
if credentials.password().unwrap_or("") != password {
|
||||
Err((AuthenticationError::new(Basic::new()).into(), req))
|
||||
} else {
|
||||
@@ -73,12 +81,12 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
}))
|
||||
.service(sideload::service())
|
||||
}).bind(
|
||||
config::C
|
||||
config::CFG
|
||||
.read()
|
||||
.await
|
||||
.get_string("listen.sideload")
|
||||
.unwrap_or("0.0.0.0:81".to_string())
|
||||
)?.run();
|
||||
)?.workers(1).run();
|
||||
|
||||
// Process manager
|
||||
{
|
||||
|
78
src/tls.rs
Normal file
78
src/tls.rs
Normal file
@@ -0,0 +1,78 @@
|
||||
use std::fs::File;
|
||||
use std::{error};
|
||||
use std::io::BufReader;
|
||||
use std::sync::Arc;
|
||||
use config::ConfigError;
|
||||
use lazy_static::lazy_static;
|
||||
use rustls::crypto::ring::sign::RsaSigningKey;
|
||||
use rustls::server::{ClientHello, ResolvesServerCert};
|
||||
use rustls::sign::CertifiedKey;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Mutex;
|
||||
use wildmatch::WildMatch;
|
||||
|
||||
lazy_static! {
|
||||
static ref CERTS: Mutex<Vec<CertificateConfig>> = Mutex::new(Vec::new());
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ProxyCertResolver;
|
||||
|
||||
impl ResolvesServerCert for ProxyCertResolver {
|
||||
fn resolve(&self, handshake: ClientHello) -> Option<Arc<CertifiedKey>> {
|
||||
let domain = handshake.server_name()?;
|
||||
|
||||
let certs = CERTS.lock().unwrap();
|
||||
for cert in certs.iter() {
|
||||
if WildMatch::new(cert.domain.as_str()).matches(domain) {
|
||||
return match cert.clone().load() {
|
||||
Ok(val) => Some(val),
|
||||
Err(_) => None
|
||||
};
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
struct CertificateConfig {
|
||||
pub domain: String,
|
||||
pub certs: String,
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
impl CertificateConfig {
|
||||
pub fn load(self) -> Result<Arc<CertifiedKey>, Box<dyn error::Error>> {
|
||||
let certs =
|
||||
rustls_pemfile::certs(&mut BufReader::new(&mut File::open(self.certs)?))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let key =
|
||||
rustls_pemfile::private_key(&mut BufReader::new(&mut File::open(self.key)?))?
|
||||
.unwrap();
|
||||
let sign = RsaSigningKey::new(&key)?;
|
||||
|
||||
Ok(Arc::new(CertifiedKey::new(certs, Arc::new(sign))))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn load_certificates() -> Result<(), ConfigError> {
|
||||
let certs = crate::config::CFG
|
||||
.read()
|
||||
.await
|
||||
.get::<Vec<CertificateConfig>>("certificates")?;
|
||||
|
||||
CERTS.lock().unwrap().clone_from(&certs);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn use_rustls() -> Result<rustls::ServerConfig, ConfigError> {
|
||||
load_certificates().await?;
|
||||
|
||||
Ok(
|
||||
rustls::ServerConfig::builder()
|
||||
.with_no_client_auth()
|
||||
.with_cert_resolver(Arc::new(ProxyCertResolver))
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user