checkpoint: integrate authenticated transports
This commit is contained in:
1 parent
313ab00765
commit
586ff8f223
42 files changed
+6277
-771
No files matched your search
@@ -1,22 +1,16 @@
|
||||
#[path = "../src/config.rs"]
|
||||
mod config;
|
||||
#[path = "../src/datagram.rs"]
|
||||
mod datagram;
|
||||
#[path = "../src/protocol/mod.rs"]
|
||||
mod protocol;
|
||||
#[path = "../src/stats.rs"]
|
||||
mod stats;
|
||||
#[path = "../src/transport/mod.rs"]
|
||||
mod transport;
|
||||
|
||||
use std::{process::Command, sync::Arc, time::Duration};
|
||||
|
||||
use bytes::Bytes;
|
||||
use config::Config;
|
||||
use rustls::RootCertStore;
|
||||
use tempfile::tempdir;
|
||||
use tokio::time::timeout;
|
||||
use transport::{TlsTcpConnector, TlsTcpServer, TransportConnector, TransportSession};
|
||||
use wgcloak::{
|
||||
config::Config,
|
||||
protocol, transport,
|
||||
transport::{
|
||||
AdmissionController, TlsTcpConnector, TlsTcpServer, TransportConnector, TransportError,
|
||||
},
|
||||
};
|
||||
|
||||
const SECRET: &str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
||||
|
||||
@@ -29,7 +23,7 @@ fn free_port() -> u16 {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn tls_tcp_authenticates_and_round_trips_opaque_datagrams() {
|
||||
async fn tls_tcp_authenticates_round_trips_and_classifies_failures() {
|
||||
if Command::new("openssl").arg("version").output().is_err() {
|
||||
return;
|
||||
}
|
||||
@@ -45,6 +39,10 @@ async fn tls_tcp_authenticates_and_round_trips_opaque_datagrams() {
|
||||
"-nodes",
|
||||
"-subj",
|
||||
"/CN=localhost",
|
||||
"-addext",
|
||||
"subjectAltName=DNS:localhost",
|
||||
"-addext",
|
||||
"basicConstraints=critical,CA:FALSE",
|
||||
"-days",
|
||||
"1",
|
||||
"-keyout",
|
||||
@@ -61,7 +59,7 @@ async fn tls_tcp_authenticates_and_round_trips_opaque_datagrams() {
|
||||
);
|
||||
let port = free_port();
|
||||
let server_config = Config::from_str(&format!(
|
||||
"[server]\nlisten = \"127.0.0.1\"\n[backend]\ntarget = \"127.0.0.1:51820\"\n[transports.direct_udp]\nenabled = false\n[transports.quic]\nenabled = false\n[transports.http3]\nenabled = false\n[transports.tls_tcp]\nenabled = true\nport = {port}\n[tls]\ncertificate = \"{}\"\nprivate_key = \"{}\"\n[[auth.clients]]\nid = \"test\"\nsecret = \"{SECRET}\"\n",
|
||||
"[server]\nlisten = \"127.0.0.1\"\n[backend]\ntarget = \"127.0.0.1:51820\"\n[transports.direct_udp]\nenabled = false\n[transports.quic]\nenabled = false\n[transports.http3]\nenabled = false\n[transports.tls_tcp]\nenabled = true\nport = {port}\n[limits]\nhandshake_timeout_ms = 500\n[tls]\ncertificate = \"{}\"\nprivate_key = \"{}\"\n[[auth.clients]]\nid = \"test\"\nsecret = \"{SECRET}\"\n",
|
||||
cert.display(),
|
||||
key.display()
|
||||
))
|
||||
@@ -69,23 +67,47 @@ async fn tls_tcp_authenticates_and_round_trips_opaque_datagrams() {
|
||||
.into_server()
|
||||
.unwrap();
|
||||
let client_config = Config::from_str(&format!(
|
||||
"[client]\nserver = \"localhost\"\nid = \"test\"\nsecret = \"{SECRET}\"\n[transport]\nmode = \"tls_tcp\"\n[transport.tls_tcp]\nport = {port}\n[network]\nmax_datagram_size = 1200\n"
|
||||
"[client]\nserver = \"localhost\"\nid = \"test\"\nsecret = \"{SECRET}\"\n[transport]\nmode = \"tls_tcp\"\n[transport.tls_tcp]\nport = {port}\nkeepalive_secs = 1\n[network]\nmax_datagram_size = 1200\n"
|
||||
))
|
||||
.unwrap()
|
||||
.into_client()
|
||||
.unwrap();
|
||||
let mismatch_config = client_config.clone();
|
||||
let certs = transport::tls_tcp::load_certificates(&cert).unwrap();
|
||||
let mut roots = RootCertStore::empty();
|
||||
roots.add(certs[0].clone()).unwrap();
|
||||
let client_tls = (*transport::tls_tcp::client_tls_config(roots)).clone();
|
||||
let server = Arc::new(TlsTcpServer::bind(&server_config).await.unwrap());
|
||||
let admission = AdmissionController::new(&server_config.limits);
|
||||
let server = Arc::new(
|
||||
TlsTcpServer::bind_with_admission(&server_config, admission.clone())
|
||||
.await
|
||||
.unwrap(),
|
||||
);
|
||||
let slow_server = server.clone();
|
||||
let slow_handshake = tokio::spawn(async move { slow_server.accept_session().await });
|
||||
let slow_peer = tokio::net::TcpStream::connect(server.local_addr().unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
tokio::time::sleep(Duration::from_millis(50)).await;
|
||||
let accept = {
|
||||
let server = server.clone();
|
||||
tokio::spawn(async move { server.accept_session().await })
|
||||
};
|
||||
let client = TlsTcpConnector::with_client_config(client_config, client_tls);
|
||||
let client = TlsTcpConnector::with_client_config(client_config, client_tls.clone());
|
||||
let client_session = client.connect().await.unwrap();
|
||||
let server_session = accept.await.unwrap().unwrap();
|
||||
assert_eq!(
|
||||
client_session.authenticated_keepalive_interval(),
|
||||
Some(Duration::from_secs(1))
|
||||
);
|
||||
assert_eq!(client_session.rtt(), None);
|
||||
assert_eq!(
|
||||
client_session.remote_addr().unwrap().ip(),
|
||||
"127.0.0.1".parse::<std::net::IpAddr>().unwrap()
|
||||
);
|
||||
assert_eq!(admission.active_sessions(), 1);
|
||||
assert_eq!(admission.pending_handshakes(), 1);
|
||||
client_session.send_keepalive().await.unwrap();
|
||||
client_session
|
||||
.send_datagram(Bytes::from_static(b"tls-opaque"))
|
||||
.await
|
||||
@@ -99,4 +121,59 @@ async fn tls_tcp_authenticates_and_round_trips_opaque_datagrams() {
|
||||
);
|
||||
client_session.close().await.unwrap();
|
||||
server_session.close().await.unwrap();
|
||||
assert!(matches!(
|
||||
timeout(Duration::from_secs(1), slow_handshake)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Err(TransportError::HandshakeTimeout)
|
||||
));
|
||||
drop(slow_peer);
|
||||
assert_eq!(admission.active_sessions(), 0);
|
||||
assert_eq!(admission.pending_handshakes(), 0);
|
||||
|
||||
let mut wrong_credentials = mismatch_config.clone();
|
||||
wrong_credentials.client.secret.secret =
|
||||
Some("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB".to_owned());
|
||||
let server_accept = {
|
||||
let server = server.clone();
|
||||
tokio::spawn(async move { server.accept_session().await })
|
||||
};
|
||||
let wrong_client = TlsTcpConnector::with_client_config(wrong_credentials, client_tls.clone());
|
||||
assert!(matches!(
|
||||
timeout(Duration::from_secs(2), wrong_client.connect())
|
||||
.await
|
||||
.unwrap(),
|
||||
Err(TransportError::AuthenticationRejected(
|
||||
protocol::RejectReason::AuthenticationFailed
|
||||
))
|
||||
));
|
||||
assert!(matches!(
|
||||
timeout(Duration::from_secs(2), server_accept)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Err(TransportError::AuthenticationRejected(
|
||||
protocol::RejectReason::AuthenticationFailed
|
||||
))
|
||||
));
|
||||
|
||||
let server_accept = {
|
||||
let server = server.clone();
|
||||
tokio::spawn(async move { server.accept_session().await })
|
||||
};
|
||||
let mut mismatch_config = mismatch_config;
|
||||
mismatch_config.client.server = "127.0.0.1".to_owned();
|
||||
let mismatch_client = TlsTcpConnector::with_client_config(mismatch_config, client_tls);
|
||||
assert!(matches!(
|
||||
timeout(Duration::from_secs(2), mismatch_client.connect())
|
||||
.await
|
||||
.unwrap(),
|
||||
Err(TransportError::Io(_))
|
||||
));
|
||||
assert!(timeout(Duration::from_secs(2), server_accept)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.is_err());
|
||||
}
|
||||
Reference in new issue
Block a user