Bump dependencies
This commit is contained in:
parent
1eccb70aab
commit
bf9459b3fc
6 changed files with 971 additions and 291 deletions
1091
Cargo.lock
generated
1091
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
32
Cargo.toml
32
Cargo.toml
|
@ -7,9 +7,10 @@ repository = "https://github.com/erebe/wstunnel.git"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ahash = { version = "0.8.11", features = [] }
|
ahash = { version = "0.8.11", features = [] }
|
||||||
anyhow = "1.0.81"
|
anyhow = "1.0.83"
|
||||||
async-trait = "0.1.79"
|
async-trait = "0.1.80"
|
||||||
base64 = "0.22.0"
|
base64 = "0.22.1"
|
||||||
|
scopeguard = "1.2.0"
|
||||||
|
|
||||||
bb8 = { version = "0.8", features = [] }
|
bb8 = { version = "0.8", features = [] }
|
||||||
bytes = { version = "1.6.0", features = [] }
|
bytes = { version = "1.6.0", features = [] }
|
||||||
|
@ -17,7 +18,7 @@ clap = { version = "4.5.4", features = ["derive", "env"] }
|
||||||
fast-socks5 = { version = "0.9.6", features = [] }
|
fast-socks5 = { version = "0.9.6", features = [] }
|
||||||
fastwebsockets = { version = "0.7.1", features = ["upgrade", "simd", "unstable-split"] }
|
fastwebsockets = { version = "0.7.1", features = ["upgrade", "simd", "unstable-split"] }
|
||||||
futures-util = { version = "0.3.30" }
|
futures-util = { version = "0.3.30" }
|
||||||
hickory-resolver = { version = "0.24.0", features = ["tokio", "dns-over-https-rustls", "dns-over-rustls"] }
|
hickory-resolver = { version = "0.24.1", features = ["tokio", "dns-over-https-rustls", "dns-over-rustls"] }
|
||||||
ppp = { version = "2.2.0", features = [] }
|
ppp = { version = "2.2.0", features = [] }
|
||||||
|
|
||||||
# For config file parsing
|
# For config file parsing
|
||||||
|
@ -26,27 +27,30 @@ serde_regex = "1.1.0"
|
||||||
serde_yaml = { version = "0.9.34", features = [] }
|
serde_yaml = { version = "0.9.34", features = [] }
|
||||||
ipnet = { version = "2.9.0", features = ["serde"] }
|
ipnet = { version = "2.9.0", features = ["serde"] }
|
||||||
|
|
||||||
hyper = { version = "1.2.0", features = ["client", "http1", "http2"] }
|
hyper = { version = "1.3.1", features = ["client", "http1", "http2"] }
|
||||||
hyper-util = { version = "0.1.3", features = ["tokio", "server", "server-auto"] }
|
hyper-util = { version = "0.1.3", features = ["tokio", "server", "server-auto"] }
|
||||||
http-body-util = { version = "0.1.1" }
|
http-body-util = { version = "0.1.1" }
|
||||||
jsonwebtoken = { version = "9.3.0", default-features = false }
|
jsonwebtoken = { version = "9.3.0", default-features = false }
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
nix = { version = "0.28.0", features = ["socket", "net", "uio"] }
|
nix = { version = "0.28.0", features = ["socket", "net", "uio"] }
|
||||||
once_cell = { version = "1.19.0", features = [] }
|
once_cell = { version = "1.19.0", features = [] }
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.2"
|
||||||
pin-project = "1"
|
pin-project = "1"
|
||||||
notify = { version = "6.1.1", features = [] }
|
notify = { version = "6.1.1", features = [] }
|
||||||
|
|
||||||
rustls-native-certs = { version = "0.7.0", features = [] }
|
rustls-native-certs = { version = "0.7.0", features = [] }
|
||||||
rustls-pemfile = { version = "2.1.1", features = [] }
|
rustls-pemfile = { version = "2.1.2", features = [] }
|
||||||
x509-parser = "0.16.0"
|
x509-parser = "0.16.0"
|
||||||
scopeguard = "1.2.0"
|
serde = { version = "1.0.201", features = ["derive"] }
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
socket2 = { version = "0.5.7", features = [] }
|
||||||
socket2 = { version = "0.5.6", features = [] }
|
tokio = { version = "1.37.0", features = ["full"] }
|
||||||
tokio = { version = "1.36.0", features = ["full"] }
|
|
||||||
tokio-rustls = { version = "0.24.1", features = ["tls12", "dangerous_configuration", "early-data"] }
|
|
||||||
tokio-stream = { version = "0.1.15", features = ["net"] }
|
tokio-stream = { version = "0.1.15", features = ["net"] }
|
||||||
|
|
||||||
|
[target.'cfg(os = "linux")'.dependencies]
|
||||||
|
tokio-rustls = { version = "0.26.0", features = ["tls12"] }
|
||||||
|
[target.'cfg(not(os = "linux"))'.dependencies]
|
||||||
|
tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "tls12", "ring"] }
|
||||||
|
|
||||||
tracing = { version = "0.1.40", features = ["log"] }
|
tracing = { version = "0.1.40", features = ["log"] }
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "fmt", "local-time"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "fmt", "local-time"] }
|
||||||
url = "2.5.0"
|
url = "2.5.0"
|
||||||
|
@ -55,13 +59,13 @@ uuid = { version = "1.8.0", features = ["v7", "serde"] }
|
||||||
|
|
||||||
[target.'cfg(not(target_family = "unix"))'.dependencies]
|
[target.'cfg(not(target_family = "unix"))'.dependencies]
|
||||||
crossterm = { version = "0.27.0" }
|
crossterm = { version = "0.27.0" }
|
||||||
tokio-util = { version = "0.7.10", features = ["io"] }
|
tokio-util = { version = "0.7.11", features = ["io"] }
|
||||||
|
|
||||||
[target.'cfg(target_family = "unix")'.dependencies]
|
[target.'cfg(target_family = "unix")'.dependencies]
|
||||||
tokio-fd = "0.3.0"
|
tokio-fd = "0.3.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
testcontainers = "0.15.0"
|
testcontainers = "0.16.7"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use log::info;
|
use log::info;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use tokio_rustls::rustls::{Certificate, PrivateKey};
|
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
|
||||||
|
|
||||||
pub static TLS_PRIVATE_KEY: Lazy<PrivateKey> = Lazy::new(|| {
|
pub static TLS_PRIVATE_KEY: Lazy<PrivateKeyDer<'static>> = Lazy::new(|| {
|
||||||
info!("Loading embedded tls private key");
|
info!("Loading embedded tls private key");
|
||||||
|
|
||||||
let key = include_bytes!("../certs/key.pem");
|
let key = include_bytes!("../certs/key.pem");
|
||||||
let key = rustls_pemfile::private_key(&mut key.as_slice())
|
let key = rustls_pemfile::private_key(&mut key.as_slice())
|
||||||
.expect("failed to load embedded tls private key")
|
.expect("failed to load embedded tls private key")
|
||||||
.expect("failed to load embedded tls private key");
|
.expect("failed to load embedded tls private key");
|
||||||
PrivateKey(key.secret_der().to_vec())
|
key
|
||||||
});
|
});
|
||||||
pub static TLS_CERTIFICATE: Lazy<Vec<Certificate>> = Lazy::new(|| {
|
pub static TLS_CERTIFICATE: Lazy<Vec<CertificateDer<'static>>> = Lazy::new(|| {
|
||||||
info!("Loading embedded tls certificate");
|
info!("Loading embedded tls certificate");
|
||||||
|
|
||||||
let cert = include_bytes!("../certs/cert.pem");
|
let cert = include_bytes!("../certs/cert.pem");
|
||||||
|
@ -19,8 +19,5 @@ pub static TLS_CERTIFICATE: Lazy<Vec<Certificate>> = Lazy::new(|| {
|
||||||
.next()
|
.next()
|
||||||
.expect("failed to load embedded tls certificate");
|
.expect("failed to load embedded tls certificate");
|
||||||
|
|
||||||
certs
|
certs.into_iter().collect()
|
||||||
.into_iter()
|
|
||||||
.map(|cert| Certificate(cert.as_ref().to_vec()))
|
|
||||||
.collect()
|
|
||||||
});
|
});
|
||||||
|
|
30
src/main.rs
30
src/main.rs
|
@ -34,8 +34,7 @@ use std::{fmt, io};
|
||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
use tokio::io::{AsyncRead, AsyncWrite};
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
use tokio_rustls::rustls::server::DnsName;
|
use tokio_rustls::rustls::pki_types::{CertificateDer, DnsName, PrivateKeyDer, ServerName};
|
||||||
use tokio_rustls::rustls::{Certificate, PrivateKey, ServerName};
|
|
||||||
use tokio_rustls::TlsConnector;
|
use tokio_rustls::TlsConnector;
|
||||||
|
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
|
@ -143,7 +142,7 @@ struct Client {
|
||||||
/// Warning: If you are behind a CDN (i.e: Cloudflare) you must set this domain also in the http HOST header.
|
/// Warning: If you are behind a CDN (i.e: Cloudflare) you must set this domain also in the http HOST header.
|
||||||
/// or it will be flagged as fishy and your request rejected
|
/// or it will be flagged as fishy and your request rejected
|
||||||
#[arg(long, value_name = "DOMAIN_NAME", value_parser = parse_sni_override, verbatim_doc_comment)]
|
#[arg(long, value_name = "DOMAIN_NAME", value_parser = parse_sni_override, verbatim_doc_comment)]
|
||||||
tls_sni_override: Option<DnsName>,
|
tls_sni_override: Option<DnsName<'static>>,
|
||||||
|
|
||||||
/// Disable sending SNI during TLS handshake
|
/// Disable sending SNI during TLS handshake
|
||||||
/// Warning: Most reverse proxies rely on it
|
/// Warning: Most reverse proxies rely on it
|
||||||
|
@ -534,7 +533,7 @@ fn parse_tunnel_arg(arg: &str) -> Result<LocalToRemote, io::Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_sni_override(arg: &str) -> Result<DnsName, io::Error> {
|
fn parse_sni_override(arg: &str) -> Result<DnsName<'static>, io::Error> {
|
||||||
match DnsName::try_from(arg.to_string()) {
|
match DnsName::try_from(arg.to_string()) {
|
||||||
Ok(val) => Ok(val),
|
Ok(val) => Ok(val),
|
||||||
Err(err) => Err(io::Error::new(
|
Err(err) => Err(io::Error::new(
|
||||||
|
@ -601,9 +600,9 @@ fn parse_server_url(arg: &str) -> Result<Url, io::Error> {
|
||||||
|
|
||||||
/// Find a leaf certificate in a vector of certificates. It is assumed only a single leaf certificate
|
/// Find a leaf certificate in a vector of certificates. It is assumed only a single leaf certificate
|
||||||
/// is present in the vector. The other certificates should be (intermediate) CA certificates.
|
/// is present in the vector. The other certificates should be (intermediate) CA certificates.
|
||||||
fn find_leaf_certificate(tls_certificates: &Vec<Certificate>) -> Option<X509Certificate> {
|
fn find_leaf_certificate<'a>(tls_certificates: &'a Vec<CertificateDer<'static>>) -> Option<X509Certificate<'a>> {
|
||||||
for tls_certificate in tls_certificates {
|
for tls_certificate in tls_certificates {
|
||||||
if let Ok((_, tls_certificate_x509)) = parse_x509_certificate(&tls_certificate.0) {
|
if let Ok((_, tls_certificate_x509)) = parse_x509_certificate(tls_certificate) {
|
||||||
if !tls_certificate_x509.is_ca() {
|
if !tls_certificate_x509.is_ca() {
|
||||||
return Some(tls_certificate_x509);
|
return Some(tls_certificate_x509);
|
||||||
}
|
}
|
||||||
|
@ -626,7 +625,7 @@ fn cn_from_certificate(tls_certificate_x509: &X509Certificate) -> Option<String>
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TlsClientConfig {
|
pub struct TlsClientConfig {
|
||||||
pub tls_sni_disabled: bool,
|
pub tls_sni_disabled: bool,
|
||||||
pub tls_sni_override: Option<DnsName>,
|
pub tls_sni_override: Option<DnsName<'static>>,
|
||||||
pub tls_verify_certificate: bool,
|
pub tls_verify_certificate: bool,
|
||||||
tls_connector: Arc<RwLock<TlsConnector>>,
|
tls_connector: Arc<RwLock<TlsConnector>>,
|
||||||
pub tls_certificate_path: Option<PathBuf>,
|
pub tls_certificate_path: Option<PathBuf>,
|
||||||
|
@ -641,9 +640,9 @@ impl TlsClientConfig {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TlsServerConfig {
|
pub struct TlsServerConfig {
|
||||||
pub tls_certificate: Mutex<Vec<Certificate>>,
|
pub tls_certificate: Mutex<Vec<CertificateDer<'static>>>,
|
||||||
pub tls_key: Mutex<PrivateKey>,
|
pub tls_key: Mutex<PrivateKeyDer<'static>>,
|
||||||
pub tls_client_ca_certificates: Option<Mutex<Vec<Certificate>>>,
|
pub tls_client_ca_certificates: Option<Mutex<Vec<CertificateDer<'static>>>>,
|
||||||
pub tls_certificate_path: Option<PathBuf>,
|
pub tls_certificate_path: Option<PathBuf>,
|
||||||
pub tls_key_path: Option<PathBuf>,
|
pub tls_key_path: Option<PathBuf>,
|
||||||
pub tls_client_ca_certs_path: Option<PathBuf>,
|
pub tls_client_ca_certs_path: Option<PathBuf>,
|
||||||
|
@ -716,17 +715,16 @@ impl WsClientConfig {
|
||||||
format!("{}:{}", self.remote_addr.host(), self.remote_addr.port())
|
format!("{}:{}", self.remote_addr.host(), self.remote_addr.port())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tls_server_name(&self) -> ServerName {
|
pub fn tls_server_name(&self) -> ServerName<'static> {
|
||||||
static INVALID_DNS_NAME: Lazy<DnsName> =
|
static INVALID_DNS_NAME: Lazy<DnsName> = Lazy::new(|| DnsName::try_from("dns-name-invalid.com").unwrap());
|
||||||
Lazy::new(|| DnsName::try_from_ascii(b"dns-name-invalid.com").unwrap());
|
|
||||||
|
|
||||||
match self.remote_addr.tls().and_then(|tls| tls.tls_sni_override.as_ref()) {
|
match self.remote_addr.tls().and_then(|tls| tls.tls_sni_override.as_ref()) {
|
||||||
None => match &self.remote_addr.host() {
|
None => match &self.remote_addr.host() {
|
||||||
Host::Domain(domain) => {
|
Host::Domain(domain) => {
|
||||||
ServerName::DnsName(DnsName::try_from(domain.clone()).unwrap_or_else(|_| INVALID_DNS_NAME.clone()))
|
ServerName::DnsName(DnsName::try_from(domain.clone()).unwrap_or_else(|_| INVALID_DNS_NAME.clone()))
|
||||||
}
|
}
|
||||||
Host::Ipv4(ip) => ServerName::IpAddress(IpAddr::V4(*ip)),
|
Host::Ipv4(ip) => ServerName::IpAddress(IpAddr::V4(*ip).into()),
|
||||||
Host::Ipv6(ip) => ServerName::IpAddress(IpAddr::V6(*ip)),
|
Host::Ipv6(ip) => ServerName::IpAddress(IpAddr::V6(*ip).into()),
|
||||||
},
|
},
|
||||||
Some(sni_override) => ServerName::DnsName(sni_override.clone()),
|
Some(sni_override) => ServerName::DnsName(sni_override.clone()),
|
||||||
}
|
}
|
||||||
|
@ -1237,7 +1235,7 @@ async fn main() {
|
||||||
let tls_key = if let Some(key_path) = &args.tls_private_key {
|
let tls_key = if let Some(key_path) = &args.tls_private_key {
|
||||||
tls::load_private_key_from_file(key_path).expect("Cannot load tls private key")
|
tls::load_private_key_from_file(key_path).expect("Cannot load tls private key")
|
||||||
} else {
|
} else {
|
||||||
embedded_certificate::TLS_PRIVATE_KEY.clone()
|
embedded_certificate::TLS_PRIVATE_KEY.clone_key()
|
||||||
};
|
};
|
||||||
|
|
||||||
let tls_client_ca_certificates = args.tls_client_ca_certs.as_ref().map(|tls_client_ca| {
|
let tls_client_ca_certificates = args.tls_client_ca_certs.as_ref().map(|tls_client_ca| {
|
||||||
|
|
10
src/tcp.rs
10
src/tcp.rs
|
@ -206,7 +206,8 @@ mod tests {
|
||||||
use futures_util::pin_mut;
|
use futures_util::pin_mut;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use testcontainers::core::WaitFor;
|
use testcontainers::core::WaitFor;
|
||||||
use testcontainers::{Image, ImageArgs, RunnableImage};
|
use testcontainers::runners::AsyncRunner;
|
||||||
|
use testcontainers::{ContainerAsync, Image, ImageArgs, RunnableImage};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct MitmProxy {}
|
pub struct MitmProxy {}
|
||||||
|
@ -240,9 +241,10 @@ mod tests {
|
||||||
let server_addr: SocketAddr = "[::1]:1236".parse().unwrap();
|
let server_addr: SocketAddr = "[::1]:1236".parse().unwrap();
|
||||||
let server = TcpListener::bind(server_addr).await.unwrap();
|
let server = TcpListener::bind(server_addr).await.unwrap();
|
||||||
|
|
||||||
let docker = testcontainers::clients::Cli::default();
|
let _mitm_proxy: ContainerAsync<MitmProxy> = RunnableImage::from(MitmProxy {})
|
||||||
let mitm_proxy: RunnableImage<MitmProxy> = RunnableImage::from(MitmProxy {}).with_network("host".to_string());
|
.with_network("host".to_string())
|
||||||
let _node = docker.run(mitm_proxy);
|
.start()
|
||||||
|
.await;
|
||||||
|
|
||||||
let mut client = connect_with_http_proxy(
|
let mut client = connect_with_http_proxy(
|
||||||
&"http://localhost:8080".parse().unwrap(),
|
&"http://localhost:8080".parse().unwrap(),
|
||||||
|
|
86
src/tls.rs
86
src/tls.rs
|
@ -6,33 +6,70 @@ use log::warn;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::SystemTime;
|
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio_rustls::client::TlsStream;
|
use tokio_rustls::client::TlsStream;
|
||||||
use tokio_rustls::rustls::client::{ServerCertVerified, ServerCertVerifier};
|
|
||||||
|
|
||||||
use crate::tunnel::TransportAddr;
|
use crate::tunnel::TransportAddr;
|
||||||
use tokio_rustls::rustls::server::{AllowAnyAuthenticatedClient, NoClientAuth};
|
use tokio_rustls::rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
|
||||||
use tokio_rustls::rustls::{Certificate, ClientConfig, KeyLogFile, PrivateKey, ServerName};
|
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime};
|
||||||
|
use tokio_rustls::rustls::server::WebPkiClientVerifier;
|
||||||
|
use tokio_rustls::rustls::{ClientConfig, DigitallySignedStruct, Error, KeyLogFile, SignatureScheme};
|
||||||
use tokio_rustls::{rustls, TlsAcceptor, TlsConnector};
|
use tokio_rustls::{rustls, TlsAcceptor, TlsConnector};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct NullVerifier;
|
struct NullVerifier;
|
||||||
|
|
||||||
impl ServerCertVerifier for NullVerifier {
|
impl ServerCertVerifier for NullVerifier {
|
||||||
fn verify_server_cert(
|
fn verify_server_cert(
|
||||||
&self,
|
&self,
|
||||||
_end_entity: &Certificate,
|
_end_entity: &CertificateDer<'_>,
|
||||||
_intermediates: &[Certificate],
|
_intermediates: &[CertificateDer<'_>],
|
||||||
_server_name: &ServerName,
|
_server_name: &ServerName<'_>,
|
||||||
_scts: &mut dyn Iterator<Item = &[u8]>,
|
|
||||||
_ocsp_response: &[u8],
|
_ocsp_response: &[u8],
|
||||||
_now: SystemTime,
|
_now: UnixTime,
|
||||||
) -> Result<ServerCertVerified, rustls::Error> {
|
) -> Result<ServerCertVerified, Error> {
|
||||||
Ok(ServerCertVerified::assertion())
|
Ok(ServerCertVerified::assertion())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn verify_tls12_signature(
|
||||||
|
&self,
|
||||||
|
_message: &[u8],
|
||||||
|
_cert: &CertificateDer<'_>,
|
||||||
|
_dss: &DigitallySignedStruct,
|
||||||
|
) -> Result<HandshakeSignatureValid, Error> {
|
||||||
|
Ok(HandshakeSignatureValid::assertion())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn verify_tls13_signature(
|
||||||
|
&self,
|
||||||
|
_message: &[u8],
|
||||||
|
_cert: &CertificateDer<'_>,
|
||||||
|
_dss: &DigitallySignedStruct,
|
||||||
|
) -> Result<HandshakeSignatureValid, Error> {
|
||||||
|
Ok(HandshakeSignatureValid::assertion())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
|
||||||
|
vec![
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA1,
|
||||||
|
SignatureScheme::ECDSA_SHA1_Legacy,
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA256,
|
||||||
|
SignatureScheme::ECDSA_NISTP256_SHA256,
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA384,
|
||||||
|
SignatureScheme::ECDSA_NISTP384_SHA384,
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA512,
|
||||||
|
SignatureScheme::ECDSA_NISTP521_SHA512,
|
||||||
|
SignatureScheme::RSA_PSS_SHA256,
|
||||||
|
SignatureScheme::RSA_PSS_SHA384,
|
||||||
|
SignatureScheme::RSA_PSS_SHA512,
|
||||||
|
SignatureScheme::ED25519,
|
||||||
|
SignatureScheme::ED448,
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_certificates_from_pem(path: &Path) -> anyhow::Result<Vec<Certificate>> {
|
pub fn load_certificates_from_pem(path: &Path) -> anyhow::Result<Vec<CertificateDer<'static>>> {
|
||||||
info!("Loading tls certificate from {:?}", path);
|
info!("Loading tls certificate from {:?}", path);
|
||||||
|
|
||||||
let file = File::open(path)?;
|
let file = File::open(path)?;
|
||||||
|
@ -42,7 +79,7 @@ pub fn load_certificates_from_pem(path: &Path) -> anyhow::Result<Vec<Certificate
|
||||||
Ok(certs
|
Ok(certs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|cert| match cert {
|
.filter_map(|cert| match cert {
|
||||||
Ok(cert) => Some(Certificate(cert.to_vec())),
|
Ok(cert) => Some(cert),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("Error while parsing tls certificate: {:?}", err);
|
warn!("Error while parsing tls certificate: {:?}", err);
|
||||||
None
|
None
|
||||||
|
@ -51,7 +88,7 @@ pub fn load_certificates_from_pem(path: &Path) -> anyhow::Result<Vec<Certificate
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_private_key_from_file(path: &Path) -> anyhow::Result<PrivateKey> {
|
pub fn load_private_key_from_file(path: &Path) -> anyhow::Result<PrivateKeyDer<'static>> {
|
||||||
info!("Loading tls private key from {:?}", path);
|
info!("Loading tls private key from {:?}", path);
|
||||||
|
|
||||||
let file = File::open(path)?;
|
let file = File::open(path)?;
|
||||||
|
@ -61,30 +98,28 @@ pub fn load_private_key_from_file(path: &Path) -> anyhow::Result<PrivateKey> {
|
||||||
return Err(anyhow!("No private key found in {path:?}"));
|
return Err(anyhow!("No private key found in {path:?}"));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(PrivateKey(private_key.secret_der().to_vec()))
|
Ok(private_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tls_connector(
|
pub fn tls_connector(
|
||||||
tls_verify_certificate: bool,
|
tls_verify_certificate: bool,
|
||||||
alpn_protocols: Vec<Vec<u8>>,
|
alpn_protocols: Vec<Vec<u8>>,
|
||||||
enable_sni: bool,
|
enable_sni: bool,
|
||||||
tls_client_certificate: Option<Vec<Certificate>>,
|
tls_client_certificate: Option<Vec<CertificateDer<'static>>>,
|
||||||
tls_client_key: Option<PrivateKey>,
|
tls_client_key: Option<PrivateKeyDer<'static>>,
|
||||||
) -> anyhow::Result<TlsConnector> {
|
) -> anyhow::Result<TlsConnector> {
|
||||||
let mut root_store = rustls::RootCertStore::empty();
|
let mut root_store = rustls::RootCertStore::empty();
|
||||||
|
|
||||||
// Load system certificates and add them to the root store
|
// Load system certificates and add them to the root store
|
||||||
let certs = rustls_native_certs::load_native_certs().with_context(|| "Cannot load system certificates")?;
|
let certs = rustls_native_certs::load_native_certs().with_context(|| "Cannot load system certificates")?;
|
||||||
for cert in certs {
|
for cert in certs {
|
||||||
if let Err(err) = root_store.add(&Certificate(cert.as_ref().to_vec())) {
|
if let Err(err) = root_store.add(cert) {
|
||||||
warn!("cannot load a system certificate: {:?}", err);
|
warn!("cannot load a system certificate: {:?}", err);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let config_builder = ClientConfig::builder()
|
let config_builder = ClientConfig::builder().with_root_certificates(root_store);
|
||||||
.with_safe_defaults()
|
|
||||||
.with_root_certificates(root_store);
|
|
||||||
|
|
||||||
let mut config = match (tls_client_certificate, tls_client_key) {
|
let mut config = match (tls_client_certificate, tls_client_key) {
|
||||||
(Some(tls_client_certificate), Some(tls_client_key)) => config_builder
|
(Some(tls_client_certificate), Some(tls_client_key)) => config_builder
|
||||||
|
@ -111,19 +146,20 @@ pub fn tls_acceptor(tls_cfg: &TlsServerConfig, alpn_protocols: Option<Vec<Vec<u8
|
||||||
let mut root_store = rustls::RootCertStore::empty();
|
let mut root_store = rustls::RootCertStore::empty();
|
||||||
for tls_client_ca_certificate in tls_client_ca_certificates.lock().iter() {
|
for tls_client_ca_certificate in tls_client_ca_certificates.lock().iter() {
|
||||||
root_store
|
root_store
|
||||||
.add(tls_client_ca_certificate)
|
.add(tls_client_ca_certificate.clone())
|
||||||
.with_context(|| "Failed to add mTLS client CA certificate")?;
|
.with_context(|| "Failed to add mTLS client CA certificate")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arc::new(AllowAnyAuthenticatedClient::new(root_store))
|
WebPkiClientVerifier::builder(Arc::new(root_store))
|
||||||
|
.build()
|
||||||
|
.map_err(|err| anyhow!("Failed to build mTLS client verifier: {:?}", err))?
|
||||||
} else {
|
} else {
|
||||||
NoClientAuth::boxed()
|
WebPkiClientVerifier::no_client_auth()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut config = rustls::ServerConfig::builder()
|
let mut config = rustls::ServerConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_client_cert_verifier(client_cert_verifier)
|
.with_client_cert_verifier(client_cert_verifier)
|
||||||
.with_single_cert(tls_cfg.tls_certificate.lock().clone(), tls_cfg.tls_key.lock().clone())
|
.with_single_cert(tls_cfg.tls_certificate.lock().clone(), tls_cfg.tls_key.lock().clone_key())
|
||||||
.with_context(|| "invalid tls certificate or private key")?;
|
.with_context(|| "invalid tls certificate or private key")?;
|
||||||
|
|
||||||
config.key_log = Arc::new(KeyLogFile::new());
|
config.key_log = Arc::new(KeyLogFile::new());
|
||||||
|
|
Loading…
Reference in a new issue