use arc_swap for tls
This commit is contained in:
parent
70015a7c38
commit
9abeec89bc
5 changed files with 40 additions and 14 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -234,6 +234,12 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arc-swap"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4d7d63395147b81a9e570bcc6243aaf71c017bd666d4909cfef0085bdda8d73"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
@ -1019,6 +1025,7 @@ name = "mangadex-home"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
|
"arc-swap",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64",
|
"base64",
|
||||||
"bincode",
|
"bincode",
|
||||||
|
|
|
@ -15,6 +15,7 @@ debug = 1
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "4.0.0-beta.4", features = [ "rustls" ] }
|
actix-web = { version = "4.0.0-beta.4", features = [ "rustls" ] }
|
||||||
|
arc-swap = "1"
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
bincode = "1"
|
bincode = "1"
|
||||||
|
|
|
@ -25,6 +25,7 @@ use stop::send_stop;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::cache::MemoryLruCache;
|
use crate::cache::MemoryLruCache;
|
||||||
|
use crate::state::DynamicServerCert;
|
||||||
|
|
||||||
mod cache;
|
mod cache;
|
||||||
mod config;
|
mod config;
|
||||||
|
@ -88,7 +89,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
// What's nice is that Rustls only supports TLS 1.2 and 1.3.
|
// What's nice is that Rustls only supports TLS 1.2 and 1.3.
|
||||||
let mut tls_config = ServerConfig::new(NoClientAuth::new());
|
let mut tls_config = ServerConfig::new(NoClientAuth::new());
|
||||||
tls_config.cert_resolver = data_0.clone();
|
tls_config.cert_resolver = Arc::new(DynamicServerCert);
|
||||||
|
|
||||||
//
|
//
|
||||||
// At this point, the server is ready to start, and starts the necessary
|
// At this point, the server is ready to start, and starts the necessary
|
||||||
|
|
15
src/ping.rs
15
src/ping.rs
|
@ -11,9 +11,9 @@ use serde::{Deserialize, Serialize};
|
||||||
use sodiumoxide::crypto::box_::PrecomputedKey;
|
use sodiumoxide::crypto::box_::PrecomputedKey;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::config::CliArgs;
|
use crate::state::{PREVIOUSLY_PAUSED, TLS_CERTS, TLS_SIGNING_KEY};
|
||||||
use crate::state::PREVIOUSLY_PAUSED;
|
|
||||||
use crate::{client_api_version, state::PREVIOUSLY_COMPROMISED};
|
use crate::{client_api_version, state::PREVIOUSLY_COMPROMISED};
|
||||||
|
use crate::{config::CliArgs, state::TLS_PREVIOUSLY_CREATED};
|
||||||
use crate::{config::VALIDATE_TOKENS, state::RwLockServerState};
|
use crate::{config::VALIDATE_TOKENS, state::RwLockServerState};
|
||||||
|
|
||||||
pub const CONTROL_CENTER_PING_URL: &str = "https://api.mangadex.network/ping";
|
pub const CONTROL_CENTER_PING_URL: &str = "https://api.mangadex.network/ping";
|
||||||
|
@ -42,7 +42,9 @@ impl<'a> Request<'a> {
|
||||||
build_version: client_api_version!()
|
build_version: client_api_version!()
|
||||||
.parse()
|
.parse()
|
||||||
.expect("to parse the build version"),
|
.expect("to parse the build version"),
|
||||||
tls_created_at: Some(state.0.read().tls_config.created_at.clone()),
|
tls_created_at: TLS_PREVIOUSLY_CREATED
|
||||||
|
.get()
|
||||||
|
.map(|v| v.load().as_ref().to_owned()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +184,12 @@ pub async fn update_server_state(secret: &str, cli: &CliArgs, data: &mut Arc<RwL
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(tls) = resp.tls {
|
if let Some(tls) = resp.tls {
|
||||||
write_guard.tls_config = tls;
|
TLS_PREVIOUSLY_CREATED
|
||||||
|
.get()
|
||||||
|
.unwrap()
|
||||||
|
.swap(Arc::new(tls.created_at));
|
||||||
|
TLS_SIGNING_KEY.get().unwrap().swap(tls.priv_key);
|
||||||
|
TLS_CERTS.get().unwrap().swap(Arc::new(tls.certs));
|
||||||
}
|
}
|
||||||
|
|
||||||
let previously_compromised = PREVIOUSLY_COMPROMISED.load(Ordering::Acquire);
|
let previously_compromised = PREVIOUSLY_COMPROMISED.load(Ordering::Acquire);
|
||||||
|
|
28
src/state.rs
28
src/state.rs
|
@ -1,11 +1,13 @@
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::config::{CliArgs, SEND_SERVER_VERSION, VALIDATE_TOKENS};
|
use crate::config::{CliArgs, SEND_SERVER_VERSION, VALIDATE_TOKENS};
|
||||||
use crate::ping::{Request, Response, Tls, CONTROL_CENTER_PING_URL};
|
use crate::ping::{Request, Response, CONTROL_CENTER_PING_URL};
|
||||||
|
use arc_swap::ArcSwap;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use rustls::sign::CertifiedKey;
|
use rustls::sign::{CertifiedKey, SigningKey};
|
||||||
|
use rustls::Certificate;
|
||||||
use rustls::{ClientHello, ResolvesServerCert};
|
use rustls::{ClientHello, ResolvesServerCert};
|
||||||
use sodiumoxide::crypto::box_::PrecomputedKey;
|
use sodiumoxide::crypto::box_::PrecomputedKey;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -14,7 +16,6 @@ use url::Url;
|
||||||
pub struct ServerState {
|
pub struct ServerState {
|
||||||
pub precomputed_key: PrecomputedKey,
|
pub precomputed_key: PrecomputedKey,
|
||||||
pub image_server: Url,
|
pub image_server: Url,
|
||||||
pub tls_config: Tls,
|
|
||||||
pub url: Url,
|
pub url: Url,
|
||||||
pub url_overridden: bool,
|
pub url_overridden: bool,
|
||||||
}
|
}
|
||||||
|
@ -22,6 +23,10 @@ pub struct ServerState {
|
||||||
pub static PREVIOUSLY_PAUSED: AtomicBool = AtomicBool::new(false);
|
pub static PREVIOUSLY_PAUSED: AtomicBool = AtomicBool::new(false);
|
||||||
pub static PREVIOUSLY_COMPROMISED: AtomicBool = AtomicBool::new(false);
|
pub static PREVIOUSLY_COMPROMISED: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
pub static TLS_PREVIOUSLY_CREATED: OnceCell<ArcSwap<String>> = OnceCell::new();
|
||||||
|
pub static TLS_SIGNING_KEY: OnceCell<ArcSwap<Box<dyn SigningKey>>> = OnceCell::new();
|
||||||
|
pub static TLS_CERTS: OnceCell<ArcSwap<Vec<Certificate>>> = OnceCell::new();
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ServerInitError {
|
pub enum ServerInitError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
@ -96,10 +101,14 @@ impl ServerState {
|
||||||
VALIDATE_TOKENS.store(resp.force_tokens, Ordering::Release);
|
VALIDATE_TOKENS.store(resp.force_tokens, Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let tls = resp.tls.unwrap();
|
||||||
|
TLS_PREVIOUSLY_CREATED.set(ArcSwap::from_pointee(tls.created_at));
|
||||||
|
TLS_SIGNING_KEY.set(ArcSwap::new(tls.priv_key));
|
||||||
|
TLS_CERTS.set(ArcSwap::from_pointee(tls.certs));
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
precomputed_key: key,
|
precomputed_key: key,
|
||||||
image_server: resp.image_server,
|
image_server: resp.image_server,
|
||||||
tls_config: resp.tls.unwrap(),
|
|
||||||
url: resp.url,
|
url: resp.url,
|
||||||
url_overridden: config.override_upstream.is_some(),
|
url_overridden: config.override_upstream.is_some(),
|
||||||
})
|
})
|
||||||
|
@ -125,14 +134,15 @@ impl ServerState {
|
||||||
|
|
||||||
pub struct RwLockServerState(pub RwLock<ServerState>);
|
pub struct RwLockServerState(pub RwLock<ServerState>);
|
||||||
|
|
||||||
impl ResolvesServerCert for RwLockServerState {
|
pub struct DynamicServerCert;
|
||||||
|
|
||||||
|
impl ResolvesServerCert for DynamicServerCert {
|
||||||
fn resolve(&self, _: ClientHello) -> Option<CertifiedKey> {
|
fn resolve(&self, _: ClientHello) -> Option<CertifiedKey> {
|
||||||
// TODO: wait for actix-web to use a new version of rustls so we can
|
// TODO: wait for actix-web to use a new version of rustls so we can
|
||||||
// remove cloning the certs all the time
|
// remove cloning the certs all the time
|
||||||
let read_guard = self.0.read();
|
|
||||||
Some(CertifiedKey {
|
Some(CertifiedKey {
|
||||||
cert: read_guard.tls_config.certs.clone(),
|
cert: TLS_CERTS.get().unwrap().load().as_ref().clone(),
|
||||||
key: Arc::clone(&read_guard.tls_config.priv_key),
|
key: TLS_SIGNING_KEY.get().unwrap().load_full(),
|
||||||
ocsp: None,
|
ocsp: None,
|
||||||
sct_list: None,
|
sct_list: None,
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue