Update to modern code

This commit is contained in:
Edward Shen 2021-12-01 22:08:40 -08:00
parent 63eba4dc37
commit a838a94ce9
Signed by: edward
GPG key ID: 19182661E818369F
6 changed files with 493 additions and 512 deletions

916
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -21,7 +21,7 @@ codegen-units = 1
debug = 1 debug = 1
[dependencies] [dependencies]
actix-web = { version = "4.0.0-beta.4", features = [ "rustls" ] } actix-web = { version = "4.0.0-beta.8", features = [ "rustls" ] }
arc-swap = "1" arc-swap = "1"
async-trait = "0.1" async-trait = "0.1"
base64 = "0.13" base64 = "0.13"
@ -29,7 +29,7 @@ bincode = "1"
bytes = { version = "1", features = [ "serde" ] } bytes = { version = "1", features = [ "serde" ] }
chacha20 = "0.7" chacha20 = "0.7"
chrono = { version = "0.4", features = [ "serde" ] } chrono = { version = "0.4", features = [ "serde" ] }
clap = { version = "3.0.0-beta.2", features = [ "wrap_help" ] } clap = { version = "3.0.0-beta.4", features = [ "wrap_help" ] }
ctrlc = "3" ctrlc = "3"
dotenv = "0.15" dotenv = "0.15"
flate2 = { version = "1", features = [ "tokio" ] } flate2 = { version = "1", features = [ "tokio" ] }
@ -44,7 +44,8 @@ parking_lot = "0.11"
prometheus = { version = "0.12", features = [ "process" ] } prometheus = { version = "0.12", features = [ "process" ] }
redis = "0.21" redis = "0.21"
reqwest = { version = "0.11", default_features = false, features = [ "json", "stream", "rustls-tls" ] } reqwest = { version = "0.11", default_features = false, features = [ "json", "stream", "rustls-tls" ] }
rustls = "0.19" rustls = "0.20"
rustls-pemfile = "0.2"
serde = "1" serde = "1"
serde_json = "1" serde_json = "1"
serde_repr = "0.1" serde_repr = "0.1"

View file

@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use clap::{crate_authors, crate_description, crate_version, Clap}; use clap::{crate_authors, crate_description, crate_version, Parser};
use log::LevelFilter; use log::LevelFilter;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -301,7 +301,7 @@ struct YamlExtendedOptions {
redis_url: Option<Url>, redis_url: Option<Url>,
} }
#[derive(Clap, Clone)] #[derive(Parser, Clone)]
#[clap(version = crate_version!(), author = crate_authors!(), about = crate_description!())] #[clap(version = crate_version!(), author = crate_authors!(), about = crate_description!())]
struct CliArgs { struct CliArgs {
/// The port to listen on. /// The port to listen on.

View file

@ -22,7 +22,9 @@ use config::Config;
use maxminddb::geoip2; use maxminddb::geoip2;
use parking_lot::RwLock; use parking_lot::RwLock;
use redis::Client as RedisClient; use redis::Client as RedisClient;
use rustls::{NoClientAuth, ServerConfig};
use rustls::server::NoClientAuth;
use rustls::ServerConfig;
use sodiumoxide::crypto::stream::xchacha20::gen_key; use sodiumoxide::crypto::stream::xchacha20::gen_key;
use state::{RwLockServerState, ServerState}; use state::{RwLockServerState, ServerState};
use stop::send_stop; use stop::send_stop;
@ -239,11 +241,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
server.bind(bind_address)?.run().await?; server.bind(bind_address)?.run().await?;
} else { } else {
// Rustls only supports TLS 1.2 and 1.3. // Rustls only supports TLS 1.2 and 1.3.
let tls_config = { let tls_config = ServerConfig::builder()
let mut tls_config = ServerConfig::new(NoClientAuth::new()); .with_safe_defaults()
tls_config.cert_resolver = Arc::new(DynamicServerCert); .with_client_cert_verifier(NoClientAuth::new())
tls_config .with_cert_resolver(Arc::new(DynamicServerCert));
};
server.bind_rustls(bind_address, tls_config)?.run().await?; server.bind_rustls(bind_address, tls_config)?.run().await?;
} }

View file

@ -2,9 +2,9 @@ use std::net::{IpAddr, SocketAddr};
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use std::{io::BufReader, sync::Arc}; use std::{io::BufReader, sync::Arc};
use rustls::internal::pemfile::{certs, rsa_private_keys}; use rustls::sign::{CertifiedKey, RsaSigningKey, SigningKey};
use rustls::sign::{RSASigningKey, SigningKey}; use rustls::{Certificate, PrivateKey};
use rustls::Certificate; use rustls_pemfile::{certs, rsa_private_keys};
use serde::de::{MapAccess, Visitor}; use serde::de::{MapAccess, Visitor};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_repr::Deserialize_repr; use serde_repr::Deserialize_repr;
@ -15,8 +15,8 @@ use url::Url;
use crate::client::HTTP_CLIENT; use crate::client::HTTP_CLIENT;
use crate::config::{ClientSecret, Config}; use crate::config::{ClientSecret, Config};
use crate::state::{ use crate::state::{
RwLockServerState, PREVIOUSLY_COMPROMISED, PREVIOUSLY_PAUSED, TLS_CERTS, RwLockServerState, CERTIFIED_KEY, PREVIOUSLY_COMPROMISED, PREVIOUSLY_PAUSED,
TLS_PREVIOUSLY_CREATED, TLS_SIGNING_KEY, TLS_PREVIOUSLY_CREATED,
}; };
use crate::units::{Bytes, BytesPerSecond, Port}; use crate::units::{Bytes, BytesPerSecond, Port};
use crate::CLIENT_API_VERSION; use crate::CLIENT_API_VERSION;
@ -104,7 +104,7 @@ pub enum ErrorCode {
pub struct Tls { pub struct Tls {
pub created_at: String, pub created_at: String,
pub priv_key: Arc<Box<dyn SigningKey>>, pub priv_key: Arc<RsaSigningKey>,
pub certs: Vec<Certificate>, pub certs: Vec<Certificate>,
} }
@ -137,7 +137,8 @@ impl<'de> Deserialize<'de> for Tls {
priv_key = rsa_private_keys(&mut BufReader::new(value.as_bytes())) priv_key = rsa_private_keys(&mut BufReader::new(value.as_bytes()))
.ok() .ok()
.and_then(|mut v| { .and_then(|mut v| {
v.pop().and_then(|key| RSASigningKey::new(&key).ok()) v.pop()
.and_then(|key| RsaSigningKey::new(&PrivateKey(key)).ok())
}); });
} }
"certificate" => { "certificate" => {
@ -150,8 +151,8 @@ impl<'de> Deserialize<'de> for Tls {
match (created_at, priv_key, certificates) { match (created_at, priv_key, certificates) {
(Some(created_at), Some(priv_key), Some(certificates)) => Ok(Tls { (Some(created_at), Some(priv_key), Some(certificates)) => Ok(Tls {
created_at, created_at,
priv_key: Arc::new(Box::new(priv_key)), priv_key: Arc::new(priv_key),
certs: certificates, certs: certificates.into_iter().map(Certificate).collect(),
}), }),
_ => Err(serde::de::Error::custom("Could not deserialize tls info")), _ => Err(serde::de::Error::custom("Could not deserialize tls info")),
} }
@ -213,8 +214,12 @@ pub async fn update_server_state(
.get() .get()
.unwrap() .unwrap()
.swap(Arc::new(tls.created_at)); .swap(Arc::new(tls.created_at));
TLS_SIGNING_KEY.get().unwrap().swap(tls.priv_key); CERTIFIED_KEY.store(Some(Arc::new(CertifiedKey {
TLS_CERTS.get().unwrap().swap(Arc::new(tls.certs)); cert: tls.certs.clone(),
key: Arc::clone(&tls.priv_key) as Arc<dyn SigningKey>,
ocsp: None,
sct_list: None,
})));
} }
let previously_compromised = PREVIOUSLY_COMPROMISED.load(Ordering::Acquire); let previously_compromised = PREVIOUSLY_COMPROMISED.load(Ordering::Acquire);

View file

@ -1,15 +1,16 @@
use std::str::FromStr; use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use crate::client::HTTP_CLIENT; use crate::client::HTTP_CLIENT;
use crate::config::{ClientSecret, Config, OFFLINE_MODE}; use crate::config::{ClientSecret, Config, OFFLINE_MODE};
use crate::ping::{Request, Response, CONTROL_CENTER_PING_URL}; use crate::ping::{Request, Response, CONTROL_CENTER_PING_URL};
use arc_swap::ArcSwap; use arc_swap::{ArcSwap, ArcSwapOption};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use parking_lot::RwLock; use parking_lot::RwLock;
use rustls::sign::{CertifiedKey, SigningKey}; use rustls::server::{ClientHello, ResolvesServerCert};
use rustls::sign::{CertifiedKey, RsaSigningKey, SigningKey};
use rustls::Certificate; use rustls::Certificate;
use rustls::{ClientHello, ResolvesServerCert};
use sodiumoxide::crypto::box_::{PrecomputedKey, PRECOMPUTEDKEYBYTES}; use sodiumoxide::crypto::box_::{PrecomputedKey, PRECOMPUTEDKEYBYTES};
use thiserror::Error; use thiserror::Error;
use tracing::{error, info, warn}; use tracing::{error, info, warn};
@ -26,8 +27,10 @@ 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_PREVIOUSLY_CREATED: OnceCell<ArcSwap<String>> = OnceCell::new();
pub static TLS_SIGNING_KEY: OnceCell<ArcSwap<Box<dyn SigningKey>>> = OnceCell::new(); static TLS_SIGNING_KEY: OnceCell<ArcSwap<RsaSigningKey>> = OnceCell::new();
pub static TLS_CERTS: OnceCell<ArcSwap<Vec<Certificate>>> = OnceCell::new(); static TLS_CERTS: OnceCell<ArcSwap<Vec<Certificate>>> = OnceCell::new();
pub static CERTIFIED_KEY: ArcSwapOption<CertifiedKey> = ArcSwapOption::const_empty();
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum ServerInitError { pub enum ServerInitError {
@ -91,6 +94,14 @@ impl ServerState {
info!("This client's URL has been set to {}", resp.url); info!("This client's URL has been set to {}", resp.url);
let tls = resp.tls.unwrap(); let tls = resp.tls.unwrap();
CERTIFIED_KEY.store(Some(Arc::new(CertifiedKey {
cert: tls.certs.clone(),
key: Arc::clone(&tls.priv_key) as Arc<dyn SigningKey>,
ocsp: None,
sct_list: None,
})));
std::mem::drop( std::mem::drop(
TLS_PREVIOUSLY_CREATED.set(ArcSwap::from_pointee(tls.created_at)), TLS_PREVIOUSLY_CREATED.set(ArcSwap::from_pointee(tls.created_at)),
); );
@ -146,22 +157,9 @@ pub struct RwLockServerState(pub RwLock<ServerState>);
pub struct DynamicServerCert; pub struct DynamicServerCert;
impl ResolvesServerCert for DynamicServerCert { impl ResolvesServerCert for DynamicServerCert {
fn resolve(&self, _: ClientHello) -> Option<CertifiedKey> { fn resolve(&self, _: ClientHello) -> Option<Arc<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
Some(CertifiedKey { CERTIFIED_KEY.load_full()
cert: TLS_CERTS
.get()
.expect("tls cert to exist")
.load()
.as_ref()
.clone(),
key: TLS_SIGNING_KEY
.get()
.expect("tls signing key to exist")
.load_full(),
ocsp: None,
sct_list: None,
})
} }
} }