From a426850d640b0ab1a388b50ed1ef183e636e91fc Mon Sep 17 00:00:00 2001 From: Max Lv Date: Mon, 30 Dec 2024 13:08:34 +0800 Subject: [PATCH] Update dependencies --- Cargo.toml | 19 +++++----- src/client.rs | 23 ++++++------ src/server.rs | 96 +++++++++++++++++++++++---------------------------- 3 files changed, 64 insertions(+), 74 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9687673..502ebc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "qtun" -version = "0.2.0" +version = "0.3.0" authors = ["Max Lv "] -repository = "https://github.com/madeye/qtun" +repository = "https://github.com/shadowsocks/qtun" license = "MIT" -edition = "2021" +edition = "2024" [[bin]] name = "qtun-client" @@ -20,14 +20,17 @@ path = "src/server.rs" tokio = { version = "1", features = ["full"] } bytes = "1.2.1" futures = "0.3" -rustls = "0.21.8" -rustls-pemfile = "1.0.2" -rustls-native-certs = "0.6.1" -webpki-roots = "0.25.2" -quinn = "0.10.2" +rustls = { version = "0.23.5", default-features = false, features = ["std"] } +rustls-pemfile = "2" +rustls-platform-verifier = "0.5" +rustls-pki-types = "1.7" +webpki-roots = "0.26.7" +quinn = "0.11.6" +quinn-proto = "0.11.9" structopt = "0.3" anyhow = "1.0" tracing = "0.1" log = "0.4" env_logger = "0.10.0" dirs = "5.0.1" +rustls-native-certs = "0.8.1" diff --git a/src/client.rs b/src/client.rs index 270e295..6392f63 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,6 +1,7 @@ use std::net::SocketAddr; use std::sync::Arc; +use quinn::crypto::rustls::QuicClientConfig; use tokio::net::{TcpListener, TcpStream}; use anyhow::{anyhow, Result}; @@ -58,22 +59,15 @@ async fn main() -> Result<()> { } } - let mut roots = rustls::RootCertStore::empty(); + let mut roots = rustls::RootCertStore { + roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(), + }; - for cert in rustls_native_certs::load_native_certs().expect("could not load platform certs") { - roots.add(&rustls::Certificate(cert.0)).unwrap(); + for certs in rustls_native_certs::load_native_certs().expect("could not load platform certs") { + roots.add(certs).unwrap(); } - roots.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| { - rustls::OwnedTrustAnchor::from_subject_spki_name_constraints( - ta.subject, - ta.spki, - ta.name_constraints, - ) - })); - let mut client_crypto = rustls::ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(roots) .with_no_client_auth(); @@ -85,7 +79,10 @@ async fn main() -> Result<()> { } else { Endpoint::client("[::]:0".parse().unwrap()) }?; - endpoint.set_default_client_config(quinn::ClientConfig::new(Arc::new(client_crypto))); + let client_config = + quinn::ClientConfig::new(Arc::new(QuicClientConfig::try_from(client_crypto)?)); + + endpoint.set_default_client_config(client_config); let remote = Arc::::from(relay_addr); let host = Arc::::from(host); diff --git a/src/server.rs b/src/server.rs index 6bb30dd..c48fdf5 100644 --- a/src/server.rs +++ b/src/server.rs @@ -9,8 +9,9 @@ use env_logger::Builder; use futures::future::try_join; use futures::TryFutureExt; use log::LevelFilter; -use log::{debug, error, info}; -use rustls_pemfile::Item; +use log::{error, info}; +use quinn_proto::crypto::rustls::QuicServerConfig; +use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; use structopt::{self, StructOpt}; use tokio::net::TcpStream; @@ -50,6 +51,12 @@ struct Opt { /// Specify the host to load TLS certificates from ~/.acme.sh/host #[structopt(long = "acme-host")] acme_host: Option, + /// Client address to block + #[structopt(long = "block")] + block: Option, + /// Maximum number of concurrent connections to allow + #[structopt(long = "connection-limit")] + connection_limit: Option, } #[tokio::main] @@ -99,63 +106,31 @@ async fn main() -> Result<()> { info!("loading key: {:?}", key_path); let key = fs::read(key_path.clone()).context("failed to read private key")?; - let key = if key_path.extension().map_or(false, |x| x == "der") { - debug!("private key with DER format"); - rustls::PrivateKey(key) + let key = if key_path.extension().is_some_and(|x| x == "der") { + PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(key)) } else { - match rustls_pemfile::read_one(&mut &*key) { - Ok(x) => match x.unwrap() { - Item::RSAKey(key) => { - debug!("private key with PKCS #1 format"); - rustls::PrivateKey(key) - } - Item::PKCS8Key(key) => { - debug!("private key with PKCS #8 format"); - rustls::PrivateKey(key) - } - Item::ECKey(key) => { - debug!("private key with SEC1 format"); - rustls::PrivateKey(key) - } - Item::X509Certificate(_) => { - anyhow::bail!("you should provide a key file instead of cert"); - } - _ => { - anyhow::bail!("no private keys found"); - } - }, - Err(_) => { - anyhow::bail!("malformed private key"); - } - } + rustls_pemfile::private_key(&mut &*key) + .context("malformed PKCS #1 private key")? + .ok_or_else(|| anyhow::Error::msg("no private keys found"))? }; - let certs = fs::read(cert_path.clone()).context("failed to read certificate chain")?; - let certs = if cert_path.extension().map_or(false, |x| x == "der") { - vec![rustls::Certificate(certs)] + let certs = if cert_path.extension().is_some_and(|x| x == "der") { + vec![CertificateDer::from(certs)] } else { rustls_pemfile::certs(&mut &*certs) + .collect::>() .context("invalid PEM-encoded certificate")? - .into_iter() - .map(rustls::Certificate) - .collect() }; let mut server_crypto = rustls::ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() .with_single_cert(certs, key)?; server_crypto.alpn_protocols = common::ALPN_QUIC_HTTP.iter().map(|&x| x.into()).collect(); - let mut server_config = quinn::ServerConfig::with_crypto(Arc::new(server_crypto)); - Arc::get_mut(&mut server_config.transport) - .unwrap() - .max_concurrent_uni_streams(0_u8.into()) - .congestion_controller_factory(Arc::new(quinn::congestion::BbrConfig::default())); - - if options.stateless_retry { - server_config.use_retry(true); - } + let mut server_config = + quinn::ServerConfig::with_crypto(Arc::new(QuicServerConfig::try_from(server_crypto)?)); + let transport_config = Arc::get_mut(&mut server_config.transport).unwrap(); + transport_config.max_concurrent_uni_streams(0_u8.into()); let remote = Arc::::from(relay_addr); @@ -163,18 +138,33 @@ async fn main() -> Result<()> { eprintln!("listening on {}", endpoint.local_addr()?); while let Some(conn) = endpoint.accept().await { - info!("connection incoming"); - tokio::spawn( - handle_connection(remote.clone(), conn).unwrap_or_else(move |e| { - error!("connection failed: {reason}", reason = e.to_string()) - }), - ); + if options + .connection_limit + .is_some_and(|n| endpoint.open_connections() >= n) + { + info!("refusing due to open connection limit"); + conn.refuse(); + } else if Some(conn.remote_address()) == options.block { + info!("refusing blocked client IP address"); + conn.refuse(); + } else if options.stateless_retry && !conn.remote_address_validated() { + info!("requiring connection to validate its address"); + conn.retry().unwrap(); + } else { + info!("accepting connection"); + let fut = handle_connection(remote.clone(), conn); + tokio::spawn(async move { + if let Err(e) = fut.await { + error!("connection failed: {reason}", reason = e.to_string()) + } + }); + } } Ok(()) } -async fn handle_connection(remote: Arc, conn: quinn::Connecting) -> Result<()> { +async fn handle_connection(remote: Arc, conn: quinn::Incoming) -> Result<()> { let bi_streams = conn.await?; async {