//! This example demonstrates how to make a QUIC connection that ignores the server certificate. //! //! Checkout the `README.md` for guidance. use std::{error::Error, sync::Arc}; use scionnet::SocketAddr; use quinn::{ClientConfig, Endpoint}; mod common; use common::make_server_endpoint; #[tokio::main] async fn main() -> Result<(), Box> { // server and client are running on the same thread asynchronously let addr = "127.0.0.1:5000".parse().unwrap(); tokio::spawn(run_server(addr)); run_client(addr).await?; Ok(()) } /// Runs a QUIC server bound to given address. async fn run_server(addr: SocketAddr) { let (endpoint, _server_cert) = make_server_endpoint(addr).unwrap(); // accept a single connection let incoming_conn = endpoint.accept().await.unwrap(); let conn = incoming_conn.await.unwrap(); println!( "[server] connection accepted: addr={}", conn.remote_address() ); } async fn run_client(server_addr: SocketAddr) -> Result<(), Box> { let mut endpoint = Endpoint::client("127.0.0.1:0".parse().unwrap())?; endpoint.set_default_client_config(configure_client()); // connect to server let connection = endpoint .connect(server_addr, "localhost") .unwrap() .await .unwrap(); println!("[client] connected: addr={}", connection.remote_address()); // Dropping handles allows the corresponding objects to automatically shut down drop(connection); // Make sure the server has a chance to clean up endpoint.wait_idle().await; Ok(()) } /// Dummy certificate verifier that treats any certificate as valid. /// NOTE, such verification is vulnerable to MITM attacks, but convenient for testing. struct SkipServerVerification; impl SkipServerVerification { fn new() -> Arc { Arc::new(Self) } } impl rustls::client::ServerCertVerifier for SkipServerVerification { fn verify_server_cert( &self, _end_entity: &rustls::Certificate, _intermediates: &[rustls::Certificate], _server_name: &rustls::ServerName, _scts: &mut dyn Iterator, _ocsp_response: &[u8], _now: std::time::SystemTime, ) -> Result { Ok(rustls::client::ServerCertVerified::assertion()) } } fn configure_client() -> ClientConfig { let crypto = rustls::ClientConfig::builder() .with_safe_defaults() .with_custom_certificate_verifier(SkipServerVerification::new()) .with_no_client_auth(); ClientConfig::new(Arc::new(crypto)) }