refactor
This commit is contained in:
parent
62fe6a0b49
commit
8115bbf866
3 changed files with 37 additions and 31 deletions
|
|
@ -18,7 +18,7 @@ http3 = ["quinn", "h3", "h3-quinn"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.9.1"
|
env_logger = "0.9.1"
|
||||||
anyhow = "1.0.65"
|
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"] }
|
futures = { version = "0.3.24", features = ["alloc", "async-await"] }
|
||||||
hyper = { version = "0.14.20", default-features = false, features = [
|
hyper = { version = "0.14.20", default-features = false, features = [
|
||||||
"server",
|
"server",
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,9 @@ pub(super) fn check_client_authentication(
|
||||||
|
|
||||||
if !match_server_crypto_and_client_cert {
|
if !match_server_crypto_and_client_cert {
|
||||||
// TODO: return 403 here
|
// TODO: return 403 here
|
||||||
error!("Inconsistent client certificate for given server name");
|
error!("Inconsistent client certificate was provided for SNI");
|
||||||
return Err(RpxyError::Proxy(
|
return Err(RpxyError::Proxy(
|
||||||
"Inconsistent client certificate for given server name".to_string(),
|
"Inconsistent client certificate was provided for SNI".to_string(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,40 +70,46 @@ where
|
||||||
// spawns async handshake to avoid blocking thread by sequential handshake.
|
// spawns async handshake to avoid blocking thread by sequential handshake.
|
||||||
let handshake_fut = async move {
|
let handshake_fut = async move {
|
||||||
// timeout is introduced to avoid get stuck here.
|
// timeout is introduced to avoid get stuck here.
|
||||||
match timeout(Duration::from_secs(TLS_HANDSHAKE_TIMEOUT_SEC), acceptor.accept(raw_stream)).await {
|
let accepted = match timeout(Duration::from_secs(TLS_HANDSHAKE_TIMEOUT_SEC), acceptor.accept(raw_stream)).await {
|
||||||
Ok(x) => match x {
|
Ok(a) => a,
|
||||||
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)))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
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 {
|
self.globals.runtime_handle.spawn( async move {
|
||||||
if let Err(e) = handshake_fut.await {
|
if let Err(e) = handshake_fut.await {
|
||||||
|
|
||||||
error!("{}", e);
|
error!("{}", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue