Skip to content

Commit

Permalink
Merge 7eeed14 into e0a4237
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuef committed Jan 26, 2022
2 parents e0a4237 + 7eeed14 commit eea3c0a
Show file tree
Hide file tree
Showing 9 changed files with 316 additions and 654 deletions.
11 changes: 6 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,22 @@ bincode = "1.2.1"
bytes = { version = "1.0.1", features = ["serde"] }
futures = "~0.3.8"
igd = { version = "0.12.0", optional = true, features = ["aio"] }
quinn = { version = "0.7.0", default-features = false, features = ["tls-rustls"] }
quinn-proto = "0.7.3"
quinn = { version = "0.8.0", default-features = false, features = ["tls-rustls"] }
quinn-proto = "0.8.0"
rcgen = "~0.8.4"
rustls = { version = "0.19.0", features = ["dangerous_configuration"] }
serde = { version = "1.0.117", features = ["derive"] }
thiserror = "1.0.23"
tokio = { version = "1.2.0", features = ["sync"] }
tokio = { version = "1.12.0", features = ["sync"] }
tracing = "~0.1.26"
webpki = "~0.21.3"
rustls = { version = "0.20.2", default-features = false, features = ["quic", "dangerous_configuration"] }

[dev-dependencies]
color-eyre = "0.5.11"
ctor = "0.1.20"
rand = "~0.7.3"
tiny-keccak = { version = "2.0.2", features = ["sha3"] }
tokio = { version = "1.2.0", features = ["macros"] }
tokio = { version = "1.12.0", features = ["macros", "rt-multi-thread"] }
tracing-subscriber = "0.2.19"
tracing-test = "0.1.0"
quinn = { version = "0.8.0", default-features = false, features = ["tls-rustls", "native-certs"] }
2 changes: 1 addition & 1 deletion examples/p2p_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async fn main() -> Result<()> {
let args: Vec<String> = env::args().collect();

// create an endpoint for us to listen on and send from.
let (node, mut incoming_conns, _contact) = Endpoint::new(
let (node, mut incoming_conns, _contact) = Endpoint::new_peer(
SocketAddr::from((Ipv4Addr::LOCALHOST, 0)),
&[],
Config {
Expand Down
126 changes: 63 additions & 63 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,12 @@

//! Configuration for `Endpoint`s.

use quinn::IdleTimeout;

use rustls::{Certificate, ClientConfig, ServerName};
use serde::{Deserialize, Serialize};
use std::{future::Future, net::IpAddr, sync::Arc, time::Duration};

/// Default for [`Config::idle_timeout`] (1 minute).
///
/// This is based on average time in which routers would close the UDP mapping to the peer if they
/// see no conversation between them.
pub const DEFAULT_IDLE_TIMEOUT: Duration = Duration::from_secs(60);

/// Default for [`Config::upnp_lease_duration`] (2 minutes).
pub const DEFAULT_UPNP_LEASE_DURATION: Duration = Duration::from_secs(120);

Expand All @@ -27,6 +24,10 @@ pub const DEFAULT_UPNP_LEASE_DURATION: Duration = Duration::from_secs(120);
/// gives 5-6 retries in ~30 s total retry time.
pub const DEFAULT_INITIAL_RETRY_INTERVAL: Duration = Duration::from_millis(500);

/// Default for [`Config::idle_timeout`] (18seconds).
///
pub const DEFAULT_IDLE_TIMEOUT: Duration = Duration::from_secs(18);

/// Default for [`RetryConfig::max_retry_interval`] (15 s).
///
/// Together with the default min and multiplier,
Expand Down Expand Up @@ -57,6 +58,15 @@ pub enum ConfigError {
/// An error occurred when generating the TLS certificate.
#[error("An error occurred when generating the TLS certificate")]
CertificateGeneration(#[from] CertificateGenerationError),
/// Invalid idle timeout
#[error("An error occurred parsing idle timeout duration")]
InvalidIdleTimeout(#[from] quinn_proto::VarIntBoundsExceeded),
/// rustls error
#[error("An error occurred within rustls")]
Rustls(#[from] rustls::Error),
/// rustls error
#[error("An error occurred generaeting client config certificates")]
Webpki,
}

impl From<rcgen::RcgenError> for ConfigError {
Expand All @@ -65,18 +75,6 @@ impl From<rcgen::RcgenError> for ConfigError {
}
}

impl From<quinn::ParseError> for ConfigError {
fn from(error: quinn::ParseError) -> Self {
Self::CertificateGeneration(CertificateGenerationError(error.into()))
}
}

impl From<rustls::TLSError> for ConfigError {
fn from(error: rustls::TLSError) -> Self {
Self::CertificateGeneration(CertificateGenerationError(error.into()))
}
}

/// An error that occured when generating the TLS certificate.
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
Expand Down Expand Up @@ -223,14 +221,41 @@ pub(crate) struct InternalConfig {

impl InternalConfig {
pub(crate) fn try_from_config(config: Config) -> Result<Self> {
let idle_timeout = config.idle_timeout.unwrap_or(DEFAULT_IDLE_TIMEOUT);
let default_idle_timeout: IdleTimeout = IdleTimeout::try_from(DEFAULT_IDLE_TIMEOUT)?; // 60s

// let's convert our duration to quinn's IdleTimeout
let idle_timeout = config
.idle_timeout
.map(IdleTimeout::try_from)
.unwrap_or(Ok(default_idle_timeout))
.map_err(ConfigError::from)?;
let upnp_lease_duration = config
.upnp_lease_duration
.unwrap_or(DEFAULT_UPNP_LEASE_DURATION);
let keep_alive_interval = config.keep_alive_interval;

let transport = Self::new_transport_config(idle_timeout, config.keep_alive_interval);
let client = Self::new_client_config(transport.clone());
let server = Self::new_server_config(transport)?;
let transport = Self::new_transport_config(idle_timeout, keep_alive_interval);

// setup certificates
let mut roots = rustls::RootCertStore::empty();
let (cert, key) = Self::generate_cert()?;
roots.add(&cert).map_err(|_e| ConfigError::Webpki)?;

let mut client_crypto = ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(roots)
.with_no_client_auth();

// allow client to connect to unknown certificates, eg those generated above
client_crypto
.dangerous()
.set_certificate_verifier(Arc::new(SkipCertificateVerification));

let mut server = quinn::ServerConfig::with_single_cert(vec![cert], key)?;
server.transport = transport.clone();

let mut client = quinn::ClientConfig::new(Arc::new(client_crypto));
client.transport = transport;

Ok(Self {
client,
Expand All @@ -245,66 +270,41 @@ impl InternalConfig {
}

fn new_transport_config(
idle_timeout: Duration,
idle_timeout: IdleTimeout,
keep_alive_interval: Option<Duration>,
) -> Arc<quinn::TransportConfig> {
let mut config = quinn::TransportConfig::default();

// QUIC encodes idle timeout in a varint with max size 2^62, which is below what can be
// represented by Duration. For now, just ignore too large idle timeouts.
// FIXME: don't ignore (e.g. clamp/error/panic)?
let _ = config.max_idle_timeout(Some(idle_timeout)).ok();
let _ = config.max_idle_timeout(Some(idle_timeout));
let _ = config.keep_alive_interval(keep_alive_interval);

Arc::new(config)
}

fn new_client_config(transport: Arc<quinn::TransportConfig>) -> quinn::ClientConfig {
let mut config = quinn::ClientConfig {
transport,
..Default::default()
};
Arc::make_mut(&mut config.crypto)
.dangerous()
.set_certificate_verifier(Arc::new(SkipCertificateVerification));
config
}

fn new_server_config(transport: Arc<quinn::TransportConfig>) -> Result<quinn::ServerConfig> {
let (cert, key) = Self::generate_cert()?;

let mut config = quinn::ServerConfig::default();
config.transport = transport;

let mut config = quinn::ServerConfigBuilder::new(config);
let _ = config.certificate(quinn::CertificateChain::from_certs(vec![cert]), key)?;

Ok(config.build())
}

fn generate_cert() -> Result<(quinn::Certificate, quinn::PrivateKey)> {
fn generate_cert() -> Result<(Certificate, rustls::PrivateKey)> {
let cert = rcgen::generate_simple_self_signed(vec![SERVER_NAME.to_string()])?;

let cert_der = cert.serialize_der()?;
let key_der = cert.serialize_private_key_der();
let key = cert.serialize_private_key_der();
let cert = cert.serialize_der().unwrap();

Ok((
quinn::Certificate::from_der(&cert_der)?,
quinn::PrivateKey::from_der(&key_der)?,
))
let key = rustls::PrivateKey(key);
let cert = Certificate(cert);
Ok((cert, key))
}
}

struct SkipCertificateVerification;

impl rustls::ServerCertVerifier for SkipCertificateVerification {
impl rustls::client::ServerCertVerifier for SkipCertificateVerification {
fn verify_server_cert(
&self,
_roots: &rustls::RootCertStore,
_presented_certs: &[rustls::Certificate],
_dns_name: webpki::DNSNameRef,
_end_entity: &Certificate,
_intermediates: &[Certificate],
_server_name: &ServerName,
_scts: &mut dyn Iterator<Item = &[u8]>,
_ocsp_response: &[u8],
) -> Result<rustls::ServerCertVerified, rustls::TLSError> {
Ok(rustls::ServerCertVerified::assertion())
_now: std::time::SystemTime,
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
Ok(rustls::client::ServerCertVerified::assertion())
}
}

0 comments on commit eea3c0a

Please sign in to comment.