@@ -5,7 +5,7 @@ pub mod file_server;
55pub mod health_check;
66
77pub use attestation:: AttestationGenerator ;
8- use attestation :: { measurements :: MultiMeasurements , AttestationError , AttestationType } ;
8+
99use bytes:: Bytes ;
1010use http:: HeaderValue ;
1111use http_body_util:: { combinators:: BoxBody , BodyExt } ;
@@ -27,22 +27,21 @@ use std::time::Duration;
2727use std:: { net:: SocketAddr , sync:: Arc } ;
2828use tokio:: io:: { self , AsyncReadExt , AsyncWriteExt } ;
2929use tokio:: net:: { TcpListener , TcpStream , ToSocketAddrs } ;
30- use tokio_rustls:: rustls:: pki_types:: { CertificateDer , PrivateKeyDer , ServerName } ;
30+ use tokio_rustls:: rustls:: pki_types:: { CertificateDer , ServerName } ;
3131use tokio_rustls:: rustls:: RootCertStore ;
3232use tokio_rustls:: {
3333 rustls:: { ClientConfig , ServerConfig } ,
34- TlsAcceptor , TlsConnector ,
34+ TlsConnector ,
3535} ;
3636
37- use crate :: attestation:: { AttestationExchangeMessage , AttestationVerifier } ;
38-
39- /// This makes it possible to add breaking protocol changes and provide backwards compatibility.
40- /// When adding more supported versions, note that ordering is important. ALPN will pick the first
41- /// protocol which both parties support - so newer supported versions should come first.
42- pub const SUPPORTED_ALPN_PROTOCOL_VERSIONS : [ & [ u8 ] ; 1 ] = [ b"flashbots-ratls/1" ] ;
43-
44- /// The label used when exporting key material from a TLS session
45- const EXPORTER_LABEL : & [ u8 ; 24 ] = b"EXPORTER-Channel-Binding" ;
37+ use crate :: attestation:: {
38+ measurements:: MultiMeasurements , AttestationError , AttestationExchangeMessage , AttestationType ,
39+ AttestationVerifier ,
40+ } ;
41+ use crate :: attested_tls:: {
42+ AttestedTlsError , AttestedTlsServer , TlsCertAndKey , EXPORTER_LABEL ,
43+ SUPPORTED_ALPN_PROTOCOL_VERSIONS ,
44+ } ;
4645
4746/// The header name for giving attestation type
4847const ATTESTATION_TYPE_HEADER : & str = "X-Flashbots-Attestation-Type" ;
@@ -59,26 +58,9 @@ type RequestWithResponseSender = (
5958) ;
6059type Http2Sender = hyper:: client:: conn:: http2:: SendRequest < hyper:: body:: Incoming > ;
6160
62- /// TLS Credentials
63- pub struct TlsCertAndKey {
64- /// Der-encoded TLS certificate chain
65- pub cert_chain : Vec < CertificateDer < ' static > > ,
66- /// Der-encoded TLS private key
67- pub key : PrivateKeyDer < ' static > ,
68- }
69-
7061/// A TLS over TCP server which provides an attestation before forwarding traffic to a given target address
7162pub struct ProxyServer {
72- /// The underlying TCP listener
73- listener : TcpListener ,
74- /// Quote generation type to use (including none)
75- attestation_generator : AttestationGenerator ,
76- /// Verifier for remote attestation (including none)
77- attestation_verifier : AttestationVerifier ,
78- /// The certificate chain
79- cert_chain : Vec < CertificateDer < ' static > > ,
80- /// For accepting TLS connections
81- acceptor : TlsAcceptor ,
63+ attested_tls_server : AttestedTlsServer ,
8264 /// The address of the target service we are proxying to
8365 target : SocketAddr ,
8466}
@@ -133,38 +115,30 @@ impl ProxyServer {
133115 attestation_generator : AttestationGenerator ,
134116 attestation_verifier : AttestationVerifier ,
135117 ) -> Result < Self , ProxyError > {
136- let acceptor = tokio_rustls:: TlsAcceptor :: from ( server_config) ;
137- let listener = TcpListener :: bind ( local) . await ?;
138-
139- Ok ( Self {
140- listener,
118+ let attested_tls_server = AttestedTlsServer :: new_with_tls_config (
119+ cert_chain,
120+ server_config,
121+ local,
141122 attestation_generator,
142123 attestation_verifier,
143- acceptor,
124+ )
125+ . await ?;
126+
127+ Ok ( Self {
128+ attested_tls_server,
144129 target,
145- cert_chain,
146130 } )
147131 }
148132
149133 /// Accept an incoming connection and handle it in a seperate task
150134 pub async fn accept ( & self ) -> Result < ( ) , ProxyError > {
151- let ( inbound, _client_addr) = self . listener . accept ( ) . await ?;
135+ let target = self . target . clone ( ) ;
136+ let ( tls_stream, measurements, attestation_type) =
137+ self . attested_tls_server . accept ( ) . await ?;
152138
153- let acceptor = self . acceptor . clone ( ) ;
154- let target = self . target ;
155- let cert_chain = self . cert_chain . clone ( ) ;
156- let attestation_generator = self . attestation_generator . clone ( ) ;
157- let attestation_verifier = self . attestation_verifier . clone ( ) ;
158139 tokio:: spawn ( async move {
159- if let Err ( err) = Self :: handle_connection (
160- inbound,
161- acceptor,
162- target,
163- cert_chain,
164- attestation_generator,
165- attestation_verifier,
166- )
167- . await
140+ if let Err ( err) =
141+ Self :: handle_connection ( tls_stream, measurements, attestation_type, target) . await
168142 {
169143 warn ! ( "Failed to handle connection: {err}" ) ;
170144 }
@@ -175,74 +149,18 @@ impl ProxyServer {
175149
176150 /// Helper to get the socket address of the underlying TCP listener
177151 pub fn local_addr ( & self ) -> std:: io:: Result < SocketAddr > {
178- self . listener . local_addr ( )
152+ self . attested_tls_server . local_addr ( )
179153 }
180154
181155 /// Handle an incoming connection from a proxy-client
182156 async fn handle_connection (
183- inbound : TcpStream ,
184- acceptor : TlsAcceptor ,
157+ tls_stream : tokio_rustls:: server:: TlsStream < tokio:: net:: TcpStream > ,
158+ measurements : Option < MultiMeasurements > ,
159+ remote_attestation_type : AttestationType ,
185160 target : SocketAddr ,
186- cert_chain : Vec < CertificateDer < ' static > > ,
187- attestation_generator : AttestationGenerator ,
188- attestation_verifier : AttestationVerifier ,
189161 ) -> Result < ( ) , ProxyError > {
190162 tracing:: debug!( "proxy-server accepted connection" ) ;
191163
192- // Do TLS handshake
193- let mut tls_stream = acceptor. accept ( inbound) . await ?;
194- let ( _io, connection) = tls_stream. get_ref ( ) ;
195-
196- // Ensure that we agreed a protocol
197- let _negotiated_protocol = connection. alpn_protocol ( ) . ok_or ( ProxyError :: AlpnFailed ) ?;
198-
199- // Compute an exporter unique to the session
200- let mut exporter = [ 0u8 ; 32 ] ;
201- connection. export_keying_material (
202- & mut exporter,
203- EXPORTER_LABEL ,
204- None , // context
205- ) ?;
206-
207- let input_data = compute_report_input ( Some ( & cert_chain) , exporter) ?;
208-
209- // Get the TLS certficate chain of the client, if there is one
210- let remote_cert_chain = connection. peer_certificates ( ) . map ( |c| c. to_owned ( ) ) ;
211-
212- // If we are in a CVM, generate an attestation
213- let attestation = attestation_generator
214- . generate_attestation ( input_data)
215- . await ?
216- . encode ( ) ;
217-
218- // Write our attestation to the channel, with length prefix
219- let attestation_length_prefix = length_prefix ( & attestation) ;
220- tls_stream. write_all ( & attestation_length_prefix) . await ?;
221- tls_stream. write_all ( & attestation) . await ?;
222-
223- // Now read a length-prefixed attestation from the remote peer
224- // In the case of no client attestation this will be zero bytes
225- let mut length_bytes = [ 0 ; 4 ] ;
226- tls_stream. read_exact ( & mut length_bytes) . await ?;
227- let length: usize = u32:: from_be_bytes ( length_bytes) . try_into ( ) ?;
228-
229- let mut buf = vec ! [ 0 ; length] ;
230- tls_stream. read_exact ( & mut buf) . await ?;
231-
232- let remote_attestation_message = AttestationExchangeMessage :: decode ( & mut & buf[ ..] ) ?;
233- let remote_attestation_type = remote_attestation_message. attestation_type ;
234-
235- // If we expect an attestaion from the client, verify it and get measurements
236- let measurements = if attestation_verifier. has_remote_attestion ( ) {
237- let remote_input_data = compute_report_input ( remote_cert_chain. as_deref ( ) , exporter) ?;
238-
239- attestation_verifier
240- . verify_attestation ( remote_attestation_message, remote_input_data)
241- . await ?
242- } else {
243- None
244- } ;
245-
246164 // Setup an HTTP server
247165 let http = hyper:: server:: conn:: http2:: Builder :: new ( TokioExecutor ) ;
248166
@@ -819,6 +737,8 @@ pub enum ProxyError {
819737 Serialization ( #[ from] parity_scale_codec:: Error ) ,
820738 #[ error( "Protocol negotiation failed - remote peer does not support this protocol" ) ]
821739 AlpnFailed ,
740+ #[ error( "Attested TLS: {0}" ) ]
741+ AttestedTls ( #[ from] AttestedTlsError ) ,
822742}
823743
824744impl From < mpsc:: error:: SendError < RequestWithResponseSender > > for ProxyError {
0 commit comments