Skip to content

Commit

Permalink
Expose option for setting TLS handshake timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
Ulf Lilleengen committed Jun 3, 2022
1 parent dce57a7 commit fcba8a3
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 6 deletions.
2 changes: 2 additions & 0 deletions actix-http/src/lib.rs
Expand Up @@ -69,6 +69,8 @@ pub use self::payload::{BoxedPayloadStream, Payload, PayloadStream};
pub use self::requests::{Request, RequestHead, RequestHeadType};
pub use self::responses::{Response, ResponseBuilder, ResponseHead};
pub use self::service::HttpService;
#[cfg(any(feature = "openssl", feature = "rustls"))]
pub use self::service::TlsAcceptorConfig;

/// A major HTTP protocol version.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
Expand Down
62 changes: 60 additions & 2 deletions actix-http/src/service.rs
Expand Up @@ -181,6 +181,25 @@ where
}
}

#[cfg(any(feature = "openssl", feature = "rustls"))]
pub struct TlsAcceptorConfig {
pub(crate) handshake_timeout: Option<std::time::Duration>,
}

#[cfg(any(feature = "openssl", feature = "rustls"))]
impl TlsAcceptorConfig {
pub fn new(handshake_timeout: Option<std::time::Duration>) -> Self {
Self { handshake_timeout }
}

pub fn handshake_timeout(self, dur: std::time::Duration) -> Self {
Self {
handshake_timeout: Some(dur),
..self
}
}
}

#[cfg(feature = "openssl")]
mod openssl {
use actix_service::ServiceFactoryExt as _;
Expand Down Expand Up @@ -230,7 +249,27 @@ mod openssl {
Error = TlsError<SslError, DispatchError>,
InitError = (),
> {
Acceptor::new(acceptor)
self.openssl_with_config(acceptor, TlsAcceptorConfig::new(None))
}

/// Create OpenSSL based service with configuration.
pub fn openssl_with_config(
self,
acceptor: SslAcceptor,
tls_acceptor_config: TlsAcceptorConfig,
) -> impl ServiceFactory<
TcpStream,
Config = (),
Response = (),
Error = TlsError<SslError, DispatchError>,
InitError = (),
> {
let mut acceptor = Acceptor::new(acceptor);
if let Some(handshake_timeout) = tls_acceptor_config.handshake_timeout {
acceptor.set_handshake_timeout(handshake_timeout);
}

acceptor
.map_init_err(|_| {
unreachable!("TLS acceptor service factory does not error on init")
})
Expand Down Expand Up @@ -293,8 +332,23 @@ mod rustls {
{
/// Create Rustls based service.
pub fn rustls(
self,
config: ServerConfig,
) -> impl ServiceFactory<
TcpStream,
Config = (),
Response = (),
Error = TlsError<io::Error, DispatchError>,
InitError = (),
> {
self.rustls_with_config(config, TlsAcceptorConfig::new(None))
}

/// Create Rustls based service with configuration.
pub fn rustls_with_config(
self,
mut config: ServerConfig,
tls_acceptor_config: TlsAcceptorConfig,
) -> impl ServiceFactory<
TcpStream,
Config = (),
Expand All @@ -306,7 +360,11 @@ mod rustls {
protos.extend_from_slice(&config.alpn_protocols);
config.alpn_protocols = protos;

Acceptor::new(config)
let mut acceptor = Acceptor::new(config);
if let Some(handshake_timeout) = tls_acceptor_config.handshake_timeout {
acceptor.set_handshake_timeout(handshake_timeout);
}
acceptor
.map_init_err(|_| {
unreachable!("TLS acceptor service factory does not error on init")
})
Expand Down
8 changes: 6 additions & 2 deletions actix-http/tests/test_openssl.rs
Expand Up @@ -2,13 +2,14 @@

extern crate tls_openssl as openssl;

use std::time::Duration;
use std::{convert::Infallible, io};

use actix_http::{
body::{BodyStream, BoxBody, SizedStream},
error::PayloadError,
header::{self, HeaderValue},
Error, HttpService, Method, Request, Response, StatusCode, Version,
Error, HttpService, Method, Request, Response, StatusCode, TlsAcceptorConfig, Version,
};
use actix_http_test::test_server;
use actix_service::{fn_service, ServiceFactoryExt};
Expand Down Expand Up @@ -89,7 +90,10 @@ async fn h2_1() -> io::Result<()> {
assert_eq!(req.version(), Version::HTTP_2);
ok::<_, Error>(Response::ok())
})
.openssl(tls_config())
.openssl_with_config(
tls_config(),
TlsAcceptorConfig::new(Some(Duration::from_secs(5))),
)
.map_err(|_| ())
})
.await;
Expand Down
1 change: 1 addition & 0 deletions actix-web/CHANGES.md
Expand Up @@ -6,6 +6,7 @@
- Add `Route::wrap()` to allow individual routes to use middleware. [#2725]
- Add `ServiceConfig::default_service()`. [#2338] [#2743]
- Implement `ResponseError` for `std::convert::Infallible`
- Add `tls_handshake_timeout` server configuration option to configure TLS handshake timeout [#2752]

### Fixed
- Clear connection-level data on `HttpRequest` drop. [#2742]
Expand Down
33 changes: 31 additions & 2 deletions actix-web/src/server.rs
Expand Up @@ -18,6 +18,9 @@ use actix_tls::accept::openssl::reexports::{AlpnError, SslAcceptor, SslAcceptorB
#[cfg(feature = "rustls")]
use actix_tls::accept::rustls::reexports::ServerConfig as RustlsServerConfig;

#[cfg(any(feature = "openssl", feature = "rustls"))]
use actix_http::TlsAcceptorConfig;

use crate::{config::AppConfig, Error};

struct Socket {
Expand All @@ -30,6 +33,8 @@ struct Config {
keep_alive: KeepAlive,
client_request_timeout: Duration,
client_disconnect_timeout: Duration,
#[cfg(any(feature = "openssl", feature = "rustls"))]
tls_handshake_timeout: Option<Duration>,
}

/// An HTTP Server.
Expand Down Expand Up @@ -92,6 +97,8 @@ where
keep_alive: KeepAlive::default(),
client_request_timeout: Duration::from_secs(5),
client_disconnect_timeout: Duration::from_secs(1),
#[cfg(any(feature = "rustls", feature = "openssl"))]
tls_handshake_timeout: None,
})),
backlog: 1024,
sockets: Vec::new(),
Expand Down Expand Up @@ -225,6 +232,22 @@ where
self
}

#[cfg(any(feature = "openssl", feature = "rustls"))]
/// Set TLS handshake timeout.
///
/// Defines a timeout for TLS handshake. If the TLS handshake does not complete
/// within this time, the connection is closed.
///
/// By default handshake timeout is set to 3000 milliseconds.
pub fn tls_handshake_timeout(self, dur: Duration) -> Self {
self.config
.lock()
.unwrap()
.tls_handshake_timeout
.replace(dur);
self
}

#[doc(hidden)]
#[deprecated(since = "4.0.0", note = "Renamed to `client_disconnect_timeout`.")]
pub fn client_shutdown(self, dur: u64) -> Self {
Expand Down Expand Up @@ -379,7 +402,10 @@ where
svc.finish(map_config(fac, move |_| {
AppConfig::new(true, host.clone(), addr)
}))
.openssl(acceptor.clone())
.openssl_with_config(
acceptor.clone(),
TlsAcceptorConfig::new(c.tls_handshake_timeout),
)
})?;

Ok(self)
Expand Down Expand Up @@ -437,7 +463,10 @@ where
svc.finish(map_config(fac, move |_| {
AppConfig::new(true, host.clone(), addr)
}))
.rustls(config.clone())
.rustls_with_config(
config.clone(),
TlsAcceptorConfig::new(c.tls_handshake_timeout),
)
})?;

Ok(self)
Expand Down

0 comments on commit fcba8a3

Please sign in to comment.