Skip to content

Commit

Permalink
feat: Cert serial_number rand
Browse files Browse the repository at this point in the history
Signed-off-by: zu1k <[email protected]>
  • Loading branch information
zu1k committed Jun 5, 2022
1 parent 8c7ce46 commit 518159d
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 55 deletions.
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ tokio-util = { version = "0.7", features = ["io"] }
wildmatch = "2.1"
quick-js = { version = "0.4", features = ["log"] }
rustls = { version = "0.20", features = ["dangerous_configuration"] }
rand = "0.8.5"
34 changes: 11 additions & 23 deletions core/src/ca.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ use crate::error::Error;
use cookie::time::OffsetDateTime;
use http::uri::Authority;
use moka::future::Cache;
use rand::{thread_rng, Rng};
use rcgen::{
DistinguishedName, DnType, ExtendedKeyUsagePurpose, KeyPair, KeyUsagePurpose, RcgenError,
SanType,
};
use std::{
sync::{Arc, Mutex},
time::{SystemTime, UNIX_EPOCH},
};
use std::sync::Arc;
use time::ext::NumericalDuration;
use tokio_rustls::rustls::{self, ServerConfig};

const CERT_TTL_DAYS: u64 = 365;
const CERT_CACHE_TTL_SECONDS: u64 = CERT_TTL_DAYS * 24 * 60 * 60 / 2;

/// Issues certificates for use when communicating with clients.
///
/// Issues certificates for communicating with clients over TLS. Certificates are cached in memory
Expand All @@ -24,7 +25,6 @@ pub struct CertificateAuthority {
ca_cert: rustls::Certificate,
ca_cert_string: String,
cache: Cache<Authority, Arc<ServerConfig>>,
serial_number: Arc<Mutex<u64>>,
}

impl CertificateAuthority {
Expand All @@ -42,8 +42,10 @@ impl CertificateAuthority {
private_key,
ca_cert,
ca_cert_string,
cache: Cache::new(cache_size),
serial_number: Arc::new(Mutex::new(now_seconds())),
cache: Cache::builder()
.max_capacity(cache_size)
.time_to_live(std::time::Duration::from_secs(CERT_CACHE_TTL_SECONDS))
.build(),
};

ca.validate()?;
Expand Down Expand Up @@ -74,15 +76,9 @@ impl CertificateAuthority {
fn gen_cert(&self, authority: &Authority) -> rustls::Certificate {
let mut params = rcgen::CertificateParams::default();

{
let serial_number = Arc::clone(&self.serial_number);
let mut serial_number = serial_number.lock().unwrap();
params.serial_number = Some(*serial_number);
*serial_number += 1;
}

params.serial_number = Some(thread_rng().gen::<u64>());
params.not_before = OffsetDateTime::now_utc().saturating_sub(1.days());
params.not_after = OffsetDateTime::now_utc().saturating_add(52.weeks());
params.not_after = OffsetDateTime::now_utc().saturating_add((CERT_TTL_DAYS as i64).days());
params
.subject_alt_names
.push(SanType::DnsName(authority.host().to_string()));
Expand Down Expand Up @@ -125,11 +121,3 @@ impl CertificateAuthority {
self.ca_cert_string.clone()
}
}

fn now_seconds() -> u64 {
let start = SystemTime::now();
let since_the_epoch = start
.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
since_the_epoch.as_secs()
}
78 changes: 46 additions & 32 deletions core/src/mitm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,18 @@ pub(crate) struct MitmProxy {

impl MitmProxy {
pub(crate) async fn proxy(self, req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
match if req.method() == Method::CONNECT {
let res = if req.method() == Method::CONNECT {
self.process_connect(req).await
} else {
self.process_request(req).await
} {
Ok(resp) => Ok(allow_all_cros(resp)),
Err(e) => Err(e),
};

match res {
Ok(mut res) => {
allow_all_cros(&mut res);
Ok(res)
}
Err(err) => Err(err),
}
}

Expand All @@ -67,43 +72,42 @@ impl MitmProxy {
.unwrap_or_default()
.contains("cert.mitm")
{
return Ok(Response::builder()
.header(
http::header::CONTENT_DISPOSITION,
"attachment; filename=good-mitm.crt",
)
.header(http::header::CONTENT_TYPE, "application/octet-stream")
.status(http::StatusCode::OK)
.body(Body::from(self.ca.clone().get_cert()))
.unwrap());
return Ok(self.get_cert_res());
}

let mut req = match self.http_handler.handle_request(&mut ctx, req).await {
RequestOrResponse::Request(req) => req,
RequestOrResponse::Response(res) => return Ok(res),
};

req.headers_mut().remove(http::header::HOST);
req.headers_mut().remove(http::header::ACCEPT_ENCODING);
req.headers_mut().remove(http::header::CONTENT_LENGTH);
{
let header_mut = req.headers_mut();
header_mut.remove(http::header::HOST);
header_mut.remove(http::header::ACCEPT_ENCODING);
header_mut.remove(http::header::CONTENT_LENGTH);
}

let mut res = match self.client {
let res = match self.client {
HttpClient::Proxy(client) => client.request(req).await?,
HttpClient::Https(client) => client.request(req).await?,
};

// Remove `Strict-Transport-Security` to avoid HSTS
// See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
res.headers_mut().remove(header::STRICT_TRANSPORT_SECURITY);
let mut res = self.http_handler.handle_response(&mut ctx, res).await;
let length = res.size_hint().lower();

let mut resp = self.http_handler.handle_response(&mut ctx, res).await;
let length = resp.size_hint().lower();
{
let header_mut = res.headers_mut();

if let Some(content_length) = header_mut.get_mut(http::header::CONTENT_LENGTH) {
*content_length = HeaderValue::from_str(&length.to_string()).unwrap();
}

if let Some(content_length) = resp.headers_mut().get_mut(http::header::CONTENT_LENGTH) {
*content_length = HeaderValue::from_str(&length.to_string()).unwrap();
// Remove `Strict-Transport-Security` to avoid HSTS
// See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
header_mut.remove(header::STRICT_TRANSPORT_SECURITY);
}

Ok(resp)
Ok(res)
}

async fn process_connect(self, req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
Expand Down Expand Up @@ -186,16 +190,26 @@ impl MitmProxy {
.with_upgrades()
.await
}

fn get_cert_res(&self) -> hyper::Response<Body> {
Response::builder()
.header(
http::header::CONTENT_DISPOSITION,
"attachment; filename=good-mitm.crt",
)
.header(http::header::CONTENT_TYPE, "application/octet-stream")
.status(http::StatusCode::OK)
.body(Body::from(self.ca.clone().get_cert()))
.unwrap()
}
}

fn allow_all_cros(resp: Response<Body>) -> Response<Body> {
let mut resp = resp;
let header = resp.headers_mut();
fn allow_all_cros(res: &mut Response<Body>) {
let header_mut = res.headers_mut();
let all = HeaderValue::from_str("*").unwrap();
header.insert(http::header::ACCESS_CONTROL_ALLOW_ORIGIN, all.clone());
header.insert(http::header::ACCESS_CONTROL_ALLOW_METHODS, all.clone());
header.insert(http::header::ACCESS_CONTROL_ALLOW_METHODS, all);
resp
header_mut.insert(http::header::ACCESS_CONTROL_ALLOW_ORIGIN, all.clone());
header_mut.insert(http::header::ACCESS_CONTROL_ALLOW_METHODS, all.clone());
header_mut.insert(http::header::ACCESS_CONTROL_ALLOW_METHODS, all);
}

fn host_addr(uri: &http::Uri) -> Option<String> {
Expand Down

1 comment on commit 518159d

@vercel
Copy link

@vercel vercel bot commented on 518159d Jun 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.