feat(tls): Add flag to not send SNI during tls handshake
This commit is contained in:
parent
1c393afe4f
commit
3129fe3219
2 changed files with 42 additions and 14 deletions
20
src/main.rs
20
src/main.rs
|
@ -138,6 +138,11 @@ struct Client {
|
|||
#[arg(long, value_name = "DOMAIN_NAME", value_parser = parse_sni_override, verbatim_doc_comment)]
|
||||
tls_sni_override: Option<DnsName>,
|
||||
|
||||
/// Disable sending SNI during TLS handshake
|
||||
/// Warning: Most reverse proxies rely on it
|
||||
#[arg(long, verbatim_doc_comment)]
|
||||
tls_sni_disable: bool,
|
||||
|
||||
/// Enable TLS certificate verification.
|
||||
/// Disabled by default. The client will happily connect to any server with self signed certificate.
|
||||
#[arg(long, verbatim_doc_comment)]
|
||||
|
@ -557,6 +562,7 @@ fn parse_server_url(arg: &str) -> Result<Url, io::Error> {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct TlsClientConfig {
|
||||
pub tls_sni_disabled: bool,
|
||||
pub tls_sni_override: Option<DnsName>,
|
||||
pub tls_verify_certificate: bool,
|
||||
pub tls_connector: TlsConnector,
|
||||
|
@ -680,16 +686,26 @@ async fn main() {
|
|||
{
|
||||
TransportScheme::Ws | TransportScheme::Http => None,
|
||||
TransportScheme::Wss => Some(TlsClientConfig {
|
||||
tls_connector: tls::tls_connector(args.tls_verify_certificate, Some(vec![b"http/1.1".to_vec()]))
|
||||
tls_connector: tls::tls_connector(
|
||||
args.tls_verify_certificate,
|
||||
Some(vec![b"http/1.1".to_vec()]),
|
||||
!args.tls_sni_disable,
|
||||
)
|
||||
.expect("Cannot create tls connector"),
|
||||
tls_sni_override: args.tls_sni_override,
|
||||
tls_verify_certificate: args.tls_verify_certificate,
|
||||
tls_sni_disabled: args.tls_sni_disable,
|
||||
}),
|
||||
TransportScheme::Https => Some(TlsClientConfig {
|
||||
tls_connector: tls::tls_connector(args.tls_verify_certificate, Some(vec![b"h2".to_vec()]))
|
||||
tls_connector: tls::tls_connector(
|
||||
args.tls_verify_certificate,
|
||||
Some(vec![b"h2".to_vec()]),
|
||||
!args.tls_sni_disable,
|
||||
)
|
||||
.expect("Cannot create tls connector"),
|
||||
tls_sni_override: args.tls_sni_override,
|
||||
tls_verify_certificate: args.tls_verify_certificate,
|
||||
tls_sni_disabled: args.tls_sni_disable,
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
32
src/tls.rs
32
src/tls.rs
|
@ -66,6 +66,7 @@ pub fn load_private_key_from_file(path: &Path) -> anyhow::Result<PrivateKey> {
|
|||
pub fn tls_connector(
|
||||
tls_verify_certificate: bool,
|
||||
alpn_protocols: Option<Vec<Vec<u8>>>,
|
||||
enable_sni: bool,
|
||||
) -> anyhow::Result<TlsConnector> {
|
||||
let mut root_store = rustls::RootCertStore::empty();
|
||||
|
||||
|
@ -74,7 +75,7 @@ pub fn tls_connector(
|
|||
for cert in certs {
|
||||
if let Err(err) = root_store.add(&Certificate(cert.as_ref().to_vec())) {
|
||||
warn!("cannot load a system certificate: {:?}", err);
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,6 +84,8 @@ pub fn tls_connector(
|
|||
.with_root_certificates(root_store)
|
||||
.with_no_client_auth();
|
||||
|
||||
config.enable_sni = enable_sni;
|
||||
|
||||
// To bypass certificate verification
|
||||
if !tls_verify_certificate {
|
||||
config.dangerous().set_certificate_verifier(Arc::new(NullVerifier));
|
||||
|
@ -110,19 +113,28 @@ pub fn tls_acceptor(tls_cfg: &TlsServerConfig, alpn_protocols: Option<Vec<Vec<u8
|
|||
|
||||
pub async fn connect(client_cfg: &WsClientConfig, tcp_stream: TcpStream) -> anyhow::Result<TlsStream<TcpStream>> {
|
||||
let sni = client_cfg.tls_server_name();
|
||||
info!(
|
||||
"Doing TLS handshake using sni {sni:?} with the server {}:{}",
|
||||
client_cfg.remote_addr.host(),
|
||||
client_cfg.remote_addr.port()
|
||||
);
|
||||
|
||||
let tls_connector = match &client_cfg.remote_addr {
|
||||
TransportAddr::Wss { tls, .. } => &tls.tls_connector,
|
||||
TransportAddr::Https { tls, .. } => &tls.tls_connector,
|
||||
let (tls_connector, sni_disabled) = match &client_cfg.remote_addr {
|
||||
TransportAddr::Wss { tls, .. } => (&tls.tls_connector, tls.tls_sni_disabled),
|
||||
TransportAddr::Https { tls, .. } => (&tls.tls_connector, tls.tls_sni_disabled),
|
||||
TransportAddr::Http { .. } | TransportAddr::Ws { .. } => {
|
||||
return Err(anyhow!("Transport does not support TLS: {}", client_cfg.remote_addr.scheme()))
|
||||
}
|
||||
};
|
||||
|
||||
if sni_disabled {
|
||||
info!(
|
||||
"Doing TLS handshake without SNI with the server {}:{}",
|
||||
client_cfg.remote_addr.host(),
|
||||
client_cfg.remote_addr.port()
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
"Doing TLS handshake using SNI {sni:?} with the server {}:{}",
|
||||
client_cfg.remote_addr.host(),
|
||||
client_cfg.remote_addr.port()
|
||||
);
|
||||
}
|
||||
|
||||
let tls_stream = tls_connector.connect(sni, tcp_stream).await.with_context(|| {
|
||||
format!(
|
||||
"failed to do TLS handshake with the server {}:{}",
|
||||
|
|
Loading…
Reference in a new issue