Skip to content

Commit 057f279

Browse files
authored
Merge pull request #36 from flashbots/peg/protocol-negotiation
Add ALPN protocol negotiation
2 parents 42f7b2d + bef0ffb commit 057f279

File tree

2 files changed

+55
-9
lines changed

2 files changed

+55
-9
lines changed

src/lib.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ use tokio_rustls::{
3030

3131
use crate::attestation::{AttesationPayload, AttestationVerifier};
3232

33+
/// This makes it possible to add breaking protocol changes and provide backwards compatibility.
34+
/// When adding more supported versions, note that ordering is important. ALPN will pick the first
35+
/// protocol which both parties support - so newer supported versions should come first.
36+
pub const SUPPORTED_ALPN_PROTOCOL_VERSIONS: [&[u8]; 1] = [b"flashbots-ratls/1"];
37+
3338
/// The label used when exporting key material from a TLS session
3439
const EXPORTER_LABEL: &[u8; 24] = b"EXPORTER-Channel-Binding";
3540

@@ -85,7 +90,7 @@ impl ProxyServer {
8590
return Err(ProxyError::NoClientAuth);
8691
}
8792

88-
let server_config = if client_auth {
93+
let mut server_config = if client_auth {
8994
let root_store =
9095
RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
9196
let verifier = WebPkiClientVerifier::builder(Arc::new(root_store)).build()?;
@@ -99,6 +104,11 @@ impl ProxyServer {
99104
.with_single_cert(cert_and_key.cert_chain.clone(), cert_and_key.key)?
100105
};
101106

107+
server_config.alpn_protocols = SUPPORTED_ALPN_PROTOCOL_VERSIONS
108+
.into_iter()
109+
.map(|p| p.to_vec())
110+
.collect();
111+
102112
Self::new_with_tls_config(
103113
cert_and_key.cert_chain,
104114
server_config.into(),
@@ -179,6 +189,9 @@ impl ProxyServer {
179189
let mut tls_stream = acceptor.accept(inbound).await?;
180190
let (_io, connection) = tls_stream.get_ref();
181191

192+
// Ensure that we agreed a protocol
193+
let _negotiated_protocol = connection.alpn_protocol().ok_or(ProxyError::AlpnFailed)?;
194+
182195
// Compute an exporter unique to the session
183196
let mut exporter = [0u8; 32];
184197
connection.export_keying_material(
@@ -352,7 +365,7 @@ impl ProxyClient {
352365
};
353366

354367
// Setup TLS client configuration, with or without client auth
355-
let client_config = if let Some(ref cert_and_key) = cert_and_key {
368+
let mut client_config = if let Some(ref cert_and_key) = cert_and_key {
356369
ClientConfig::builder()
357370
.with_root_certificates(root_store)
358371
.with_client_auth_cert(
@@ -365,6 +378,11 @@ impl ProxyClient {
365378
.with_no_client_auth()
366379
};
367380

381+
client_config.alpn_protocols = SUPPORTED_ALPN_PROTOCOL_VERSIONS
382+
.into_iter()
383+
.map(|p| p.to_vec())
384+
.collect();
385+
368386
Self::new_with_tls_config(
369387
client_config.into(),
370388
address,
@@ -578,6 +596,11 @@ impl ProxyClient {
578596

579597
let (_io, server_connection) = tls_stream.get_ref();
580598

599+
// Ensure that we agreed a protocol
600+
let _negotiated_protocol = server_connection
601+
.alpn_protocol()
602+
.ok_or(ProxyError::AlpnFailed)?;
603+
581604
// Compute an exporter unique to the channel
582605
let mut exporter = [0u8; 32];
583606
server_connection.export_keying_material(
@@ -737,6 +760,8 @@ pub enum ProxyError {
737760
MpscSend,
738761
#[error("Serialization: {0}")]
739762
Serialization(#[from] parity_scale_codec::Error),
763+
#[error("Protocol negotiation failed - remote peer does not support this protocol")]
764+
AlpnFailed,
740765
}
741766

742767
impl From<mpsc::error::SendError<RequestWithResponseSender>> for ProxyError {

src/test_helpers.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use tokio_rustls::rustls::{
1313

1414
use crate::{
1515
attestation::measurements::{CvmImageMeasurements, Measurements, PlatformMeasurements},
16-
MEASUREMENT_HEADER,
16+
MEASUREMENT_HEADER, SUPPORTED_ALPN_PROTOCOL_VERSIONS,
1717
};
1818

1919
/// Helper to generate a self-signed certificate for testing
@@ -42,18 +42,27 @@ pub fn generate_tls_config(
4242
certificate_chain: Vec<CertificateDer<'static>>,
4343
key: PrivateKeyDer<'static>,
4444
) -> (Arc<ServerConfig>, Arc<ClientConfig>) {
45-
let server_config = ServerConfig::builder()
45+
let supported_protocols: Vec<_> = SUPPORTED_ALPN_PROTOCOL_VERSIONS
46+
.into_iter()
47+
.map(|p| p.to_vec())
48+
.collect();
49+
50+
let mut server_config = ServerConfig::builder()
4651
.with_no_client_auth()
4752
.with_single_cert(certificate_chain.clone(), key)
4853
.expect("Failed to create rustls server config");
4954

55+
server_config.alpn_protocols = supported_protocols.clone();
56+
5057
let mut root_store = RootCertStore::empty();
5158
root_store.add(certificate_chain[0].clone()).unwrap();
5259

53-
let client_config = ClientConfig::builder()
60+
let mut client_config = ClientConfig::builder()
5461
.with_root_certificates(root_store)
5562
.with_no_client_auth();
5663

64+
client_config.alpn_protocols = supported_protocols;
65+
5766
(Arc::new(server_config), Arc::new(client_config))
5867
}
5968

@@ -67,32 +76,44 @@ pub fn generate_tls_config_with_client_auth(
6776
(Arc<ServerConfig>, Arc<ClientConfig>),
6877
(Arc<ServerConfig>, Arc<ClientConfig>),
6978
) {
79+
let supported_protocols: Vec<_> = SUPPORTED_ALPN_PROTOCOL_VERSIONS
80+
.into_iter()
81+
.map(|p| p.to_vec())
82+
.collect();
83+
7084
let (alice_client_verifier, alice_root_store) =
7185
client_verifier_from_remote_cert(bob_certificate_chain[0].clone());
7286

73-
let alice_server_config = ServerConfig::builder()
87+
let mut alice_server_config = ServerConfig::builder()
7488
.with_client_cert_verifier(alice_client_verifier)
7589
.with_single_cert(alice_certificate_chain.clone(), alice_key.clone_key())
7690
.expect("Failed to create rustls server config");
7791

78-
let alice_client_config = ClientConfig::builder()
92+
alice_server_config.alpn_protocols = supported_protocols.clone();
93+
94+
let mut alice_client_config = ClientConfig::builder()
7995
.with_root_certificates(alice_root_store)
8096
.with_client_auth_cert(alice_certificate_chain.clone(), alice_key)
8197
.unwrap();
8298

99+
alice_client_config.alpn_protocols = supported_protocols.clone();
100+
83101
let (bob_client_verifier, bob_root_store) =
84102
client_verifier_from_remote_cert(alice_certificate_chain[0].clone());
85103

86-
let bob_server_config = ServerConfig::builder()
104+
let mut bob_server_config = ServerConfig::builder()
87105
.with_client_cert_verifier(bob_client_verifier)
88106
.with_single_cert(bob_certificate_chain.clone(), bob_key.clone_key())
89107
.expect("Failed to create rustls server config");
90108

91-
let bob_client_config = ClientConfig::builder()
109+
bob_server_config.alpn_protocols = supported_protocols.clone();
110+
111+
let mut bob_client_config = ClientConfig::builder()
92112
.with_root_certificates(bob_root_store)
93113
.with_client_auth_cert(bob_certificate_chain, bob_key)
94114
.unwrap();
95115

116+
bob_client_config.alpn_protocols = supported_protocols;
96117
(
97118
(Arc::new(alice_server_config), Arc::new(alice_client_config)),
98119
(Arc::new(bob_server_config), Arc::new(bob_client_config)),

0 commit comments

Comments
 (0)