This commit is contained in:
Jun Kurihara 2022-10-11 16:17:50 +09:00
commit 8115bbf866
No known key found for this signature in database
GPG key ID: 48ADFD173ED22B03
3 changed files with 37 additions and 31 deletions

View file

@ -18,7 +18,7 @@ http3 = ["quinn", "h3", "h3-quinn"]
[dependencies]
env_logger = "0.9.1"
anyhow = "1.0.65"
clap = { version = "4.0.10", features = ["std", "cargo", "wrap_help"] }
clap = { version = "4.0.12", features = ["std", "cargo", "wrap_help"] }
futures = { version = "0.3.24", features = ["alloc", "async-await"] }
hyper = { version = "0.14.20", default-features = false, features = [
"server",

View file

@ -46,9 +46,9 @@ pub(super) fn check_client_authentication(
if !match_server_crypto_and_client_cert {
// TODO: return 403 here
error!("Inconsistent client certificate for given server name");
error!("Inconsistent client certificate was provided for SNI");
return Err(RpxyError::Proxy(
"Inconsistent client certificate for given server name".to_string(),
"Inconsistent client certificate was provided for SNI".to_string(),
));
}

View file

@ -70,40 +70,46 @@ where
// spawns async handshake to avoid blocking thread by sequential handshake.
let handshake_fut = async move {
// timeout is introduced to avoid get stuck here.
match timeout(Duration::from_secs(TLS_HANDSHAKE_TIMEOUT_SEC), acceptor.accept(raw_stream)).await {
Ok(x) => match x {
Ok(stream) => {
// Retrieve SNI
let (_, conn) = stream.get_ref();
let server_name = conn.sni_hostname();
debug!("HTTP/2 or 1.1: SNI in ClientHello: {:?}", server_name);
let server_name = server_name.map_or_else(|| None, |v| Some(v.to_server_name_vec()));
if server_name.is_none(){
Err(RpxyError::Proxy("No SNI is given".to_string()))
} else {
//////////////////////////////
// Check client certificate
// TODO: consider move this function to the layer of handle_request (L7) to return 403
let client_certs = conn.peer_certificates();
let client_certs_setting_for_sni = sni_cc_map.get(&server_name.clone().unwrap());
check_client_authentication(client_certs, client_certs_setting_for_sni)?;
//////////////////////////////
// this immediately spawns another future to actually handle stream. so it is okay to introduce timeout for handshake.
self_inner.client_serve(stream, server_clone, client_addr, server_name); // TODO: don't want to pass copied value...
Ok(())
}
},
Err(e) => {
Err(RpxyError::Proxy(format!("Failed to handshake TLS: {}", e)))
}
},
let accepted = match timeout(Duration::from_secs(TLS_HANDSHAKE_TIMEOUT_SEC), acceptor.accept(raw_stream)).await {
Ok(a) => a,
Err(e) => {
Err(RpxyError::Proxy(format!("Timeout to handshake TLS: {}", e)))
return Err(RpxyError::Proxy(format!("Timeout to handshake TLS: {}", e)));
}
};
let stream = match accepted {
Ok(s) => s,
Err(e) => {
return Err(RpxyError::Proxy(format!("Failed to handshake TLS: {}", e)));
}
};
// Retrieve SNI
let (_, conn) = stream.get_ref();
let server_name = conn.sni_hostname();
debug!("HTTP/2 or 1.1: SNI in ClientHello: {:?}", server_name);
let server_name = server_name.map_or_else(|| None, |v| Some(v.to_server_name_vec()));
if server_name.is_none(){
// conn.send_close_notify();
Err(RpxyError::Proxy("No SNI is given".to_string()))
} else {
//////////////////////////////
// Check client certificate
// TODO: consider move this function to the layer of handle_request (L7) to return 403
let client_certs = conn.peer_certificates();
let client_certs_setting_for_sni = sni_cc_map.get(&server_name.clone().unwrap());
check_client_authentication(client_certs, client_certs_setting_for_sni)?;
// if let Err(e) = check_client_authentication(client_certs, client_certs_setting_for_sni){
// conn.send_close_notify();
// return Err(e);
// }
//////////////////////////////
// this immediately spawns another future to actually handle stream. so it is okay to introduce timeout for handshake.
self_inner.client_serve(stream, server_clone, client_addr, server_name); // TODO: don't want to pass copied value...
Ok(())
}
};
self.globals.runtime_handle.spawn( async move {
if let Err(e) = handshake_fut.await {
error!("{}", e);
}
});