Bump dependencies

This commit is contained in:
Σrebe - Romain GERARD 2024-05-09 13:33:23 +02:00
parent 1eccb70aab
commit bf9459b3fc
No known key found for this signature in database
GPG key ID: 7A42B4B97E0332F4
6 changed files with 971 additions and 291 deletions

1091
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -7,9 +7,10 @@ repository = "https://github.com/erebe/wstunnel.git"
[dependencies]
ahash = { version = "0.8.11", features = [] }
anyhow = "1.0.81"
async-trait = "0.1.79"
base64 = "0.22.0"
anyhow = "1.0.83"
async-trait = "0.1.80"
base64 = "0.22.1"
scopeguard = "1.2.0"
bb8 = { version = "0.8", 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 = [] }
fastwebsockets = { version = "0.7.1", features = ["upgrade", "simd", "unstable-split"] }
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 = [] }
# For config file parsing
@ -26,27 +27,30 @@ serde_regex = "1.1.0"
serde_yaml = { version = "0.9.34", features = [] }
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"] }
http-body-util = { version = "0.1.1" }
jsonwebtoken = { version = "9.3.0", default-features = false }
log = "0.4.21"
nix = { version = "0.28.0", features = ["socket", "net", "uio"] }
once_cell = { version = "1.19.0", features = [] }
parking_lot = "0.12.1"
parking_lot = "0.12.2"
pin-project = "1"
notify = { version = "6.1.1", 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"
scopeguard = "1.2.0"
serde = { version = "1.0.197", features = ["derive"] }
socket2 = { version = "0.5.6", features = [] }
tokio = { version = "1.36.0", features = ["full"] }
tokio-rustls = { version = "0.24.1", features = ["tls12", "dangerous_configuration", "early-data"] }
serde = { version = "1.0.201", features = ["derive"] }
socket2 = { version = "0.5.7", features = [] }
tokio = { version = "1.37.0", features = ["full"] }
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-subscriber = { version = "0.3.18", features = ["env-filter", "fmt", "local-time"] }
url = "2.5.0"
@ -55,13 +59,13 @@ uuid = { version = "1.8.0", features = ["v7", "serde"] }
[target.'cfg(not(target_family = "unix"))'.dependencies]
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]
tokio-fd = "0.3.0"
[dev-dependencies]
testcontainers = "0.15.0"
testcontainers = "0.16.7"
[profile.release]
lto = "fat"

View file

@ -1,17 +1,17 @@
use log::info;
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");
let key = include_bytes!("../certs/key.pem");
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");
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");
let cert = include_bytes!("../certs/cert.pem");
@ -19,8 +19,5 @@ pub static TLS_CERTIFICATE: Lazy<Vec<Certificate>> = Lazy::new(|| {
.next()
.expect("failed to load embedded tls certificate");
certs
.into_iter()
.map(|cert| Certificate(cert.as_ref().to_vec()))
.collect()
certs.into_iter().collect()
});

View file

@ -34,8 +34,7 @@ use std::{fmt, io};
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::net::TcpStream;
use tokio_rustls::rustls::server::DnsName;
use tokio_rustls::rustls::{Certificate, PrivateKey, ServerName};
use tokio_rustls::rustls::pki_types::{CertificateDer, DnsName, PrivateKeyDer, ServerName};
use tokio_rustls::TlsConnector;
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.
/// 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)]
tls_sni_override: Option<DnsName>,
tls_sni_override: Option<DnsName<'static>>,
/// Disable sending SNI during TLS handshake
/// 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()) {
Ok(val) => Ok(val),
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
/// 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 {
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() {
return Some(tls_certificate_x509);
}
@ -626,7 +625,7 @@ fn cn_from_certificate(tls_certificate_x509: &X509Certificate) -> Option<String>
#[derive(Clone)]
pub struct TlsClientConfig {
pub tls_sni_disabled: bool,
pub tls_sni_override: Option<DnsName>,
pub tls_sni_override: Option<DnsName<'static>>,
pub tls_verify_certificate: bool,
tls_connector: Arc<RwLock<TlsConnector>>,
pub tls_certificate_path: Option<PathBuf>,
@ -641,9 +640,9 @@ impl TlsClientConfig {
#[derive(Debug)]
pub struct TlsServerConfig {
pub tls_certificate: Mutex<Vec<Certificate>>,
pub tls_key: Mutex<PrivateKey>,
pub tls_client_ca_certificates: Option<Mutex<Vec<Certificate>>>,
pub tls_certificate: Mutex<Vec<CertificateDer<'static>>>,
pub tls_key: Mutex<PrivateKeyDer<'static>>,
pub tls_client_ca_certificates: Option<Mutex<Vec<CertificateDer<'static>>>>,
pub tls_certificate_path: Option<PathBuf>,
pub tls_key_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())
}
pub fn tls_server_name(&self) -> ServerName {
static INVALID_DNS_NAME: Lazy<DnsName> =
Lazy::new(|| DnsName::try_from_ascii(b"dns-name-invalid.com").unwrap());
pub fn tls_server_name(&self) -> ServerName<'static> {
static INVALID_DNS_NAME: Lazy<DnsName> = Lazy::new(|| DnsName::try_from("dns-name-invalid.com").unwrap());
match self.remote_addr.tls().and_then(|tls| tls.tls_sni_override.as_ref()) {
None => match &self.remote_addr.host() {
Host::Domain(domain) => {
ServerName::DnsName(DnsName::try_from(domain.clone()).unwrap_or_else(|_| INVALID_DNS_NAME.clone()))
}
Host::Ipv4(ip) => ServerName::IpAddress(IpAddr::V4(*ip)),
Host::Ipv6(ip) => ServerName::IpAddress(IpAddr::V6(*ip)),
Host::Ipv4(ip) => ServerName::IpAddress(IpAddr::V4(*ip).into()),
Host::Ipv6(ip) => ServerName::IpAddress(IpAddr::V6(*ip).into()),
},
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 {
tls::load_private_key_from_file(key_path).expect("Cannot load tls private key")
} 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| {

View file

@ -206,7 +206,8 @@ mod tests {
use futures_util::pin_mut;
use std::net::SocketAddr;
use testcontainers::core::WaitFor;
use testcontainers::{Image, ImageArgs, RunnableImage};
use testcontainers::runners::AsyncRunner;
use testcontainers::{ContainerAsync, Image, ImageArgs, RunnableImage};
#[derive(Debug, Clone, Default)]
pub struct MitmProxy {}
@ -240,9 +241,10 @@ mod tests {
let server_addr: SocketAddr = "[::1]:1236".parse().unwrap();
let server = TcpListener::bind(server_addr).await.unwrap();
let docker = testcontainers::clients::Cli::default();
let mitm_proxy: RunnableImage<MitmProxy> = RunnableImage::from(MitmProxy {}).with_network("host".to_string());
let _node = docker.run(mitm_proxy);
let _mitm_proxy: ContainerAsync<MitmProxy> = RunnableImage::from(MitmProxy {})
.with_network("host".to_string())
.start()
.await;
let mut client = connect_with_http_proxy(
&"http://localhost:8080".parse().unwrap(),

View file

@ -6,33 +6,70 @@ use log::warn;
use std::io::BufReader;
use std::path::Path;
use std::sync::Arc;
use std::time::SystemTime;
use tokio::net::TcpStream;
use tokio_rustls::client::TlsStream;
use tokio_rustls::rustls::client::{ServerCertVerified, ServerCertVerifier};
use crate::tunnel::TransportAddr;
use tokio_rustls::rustls::server::{AllowAnyAuthenticatedClient, NoClientAuth};
use tokio_rustls::rustls::{Certificate, ClientConfig, KeyLogFile, PrivateKey, ServerName};
use tokio_rustls::rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
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 tracing::info;
#[derive(Debug)]
struct NullVerifier;
impl ServerCertVerifier for NullVerifier {
fn verify_server_cert(
&self,
_end_entity: &Certificate,
_intermediates: &[Certificate],
_server_name: &ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_end_entity: &CertificateDer<'_>,
_intermediates: &[CertificateDer<'_>],
_server_name: &ServerName<'_>,
_ocsp_response: &[u8],
_now: SystemTime,
) -> Result<ServerCertVerified, rustls::Error> {
_now: UnixTime,
) -> Result<ServerCertVerified, Error> {
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);
let file = File::open(path)?;
@ -42,7 +79,7 @@ pub fn load_certificates_from_pem(path: &Path) -> anyhow::Result<Vec<Certificate
Ok(certs
.into_iter()
.filter_map(|cert| match cert {
Ok(cert) => Some(Certificate(cert.to_vec())),
Ok(cert) => Some(cert),
Err(err) => {
warn!("Error while parsing tls certificate: {:?}", err);
None
@ -51,7 +88,7 @@ pub fn load_certificates_from_pem(path: &Path) -> anyhow::Result<Vec<Certificate
.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);
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:?}"));
};
Ok(PrivateKey(private_key.secret_der().to_vec()))
Ok(private_key)
}
pub fn tls_connector(
tls_verify_certificate: bool,
alpn_protocols: Vec<Vec<u8>>,
enable_sni: bool,
tls_client_certificate: Option<Vec<Certificate>>,
tls_client_key: Option<PrivateKey>,
tls_client_certificate: Option<Vec<CertificateDer<'static>>>,
tls_client_key: Option<PrivateKeyDer<'static>>,
) -> anyhow::Result<TlsConnector> {
let mut root_store = rustls::RootCertStore::empty();
// Load system certificates and add them to the root store
let certs = rustls_native_certs::load_native_certs().with_context(|| "Cannot load system certificates")?;
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);
continue;
}
}
let config_builder = ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store);
let config_builder = ClientConfig::builder().with_root_certificates(root_store);
let mut config = match (tls_client_certificate, tls_client_key) {
(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();
for tls_client_ca_certificate in tls_client_ca_certificates.lock().iter() {
root_store
.add(tls_client_ca_certificate)
.add(tls_client_ca_certificate.clone())
.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 {
NoClientAuth::boxed()
WebPkiClientVerifier::no_client_auth()
};
let mut config = rustls::ServerConfig::builder()
.with_safe_defaults()
.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")?;
config.key_log = Arc::new(KeyLogFile::new());