mirror of https://github.com/fafhrd91/actix-web
Expose option for setting TLS handshake timeout
This commit is contained in:
parent
dce57a79c9
commit
fcba8a3858
|
@ -69,6 +69,8 @@ pub use self::payload::{BoxedPayloadStream, Payload, PayloadStream};
|
||||||
pub use self::requests::{Request, RequestHead, RequestHeadType};
|
pub use self::requests::{Request, RequestHead, RequestHeadType};
|
||||||
pub use self::responses::{Response, ResponseBuilder, ResponseHead};
|
pub use self::responses::{Response, ResponseBuilder, ResponseHead};
|
||||||
pub use self::service::HttpService;
|
pub use self::service::HttpService;
|
||||||
|
#[cfg(any(feature = "openssl", feature = "rustls"))]
|
||||||
|
pub use self::service::TlsAcceptorConfig;
|
||||||
|
|
||||||
/// A major HTTP protocol version.
|
/// A major HTTP protocol version.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -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")]
|
#[cfg(feature = "openssl")]
|
||||||
mod openssl {
|
mod openssl {
|
||||||
use actix_service::ServiceFactoryExt as _;
|
use actix_service::ServiceFactoryExt as _;
|
||||||
|
@ -230,7 +249,27 @@ mod openssl {
|
||||||
Error = TlsError<SslError, DispatchError>,
|
Error = TlsError<SslError, DispatchError>,
|
||||||
InitError = (),
|
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(|_| {
|
.map_init_err(|_| {
|
||||||
unreachable!("TLS acceptor service factory does not error on init")
|
unreachable!("TLS acceptor service factory does not error on init")
|
||||||
})
|
})
|
||||||
|
@ -293,8 +332,23 @@ mod rustls {
|
||||||
{
|
{
|
||||||
/// Create Rustls based service.
|
/// Create Rustls based service.
|
||||||
pub fn rustls(
|
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,
|
self,
|
||||||
mut config: ServerConfig,
|
mut config: ServerConfig,
|
||||||
|
tls_acceptor_config: TlsAcceptorConfig,
|
||||||
) -> impl ServiceFactory<
|
) -> impl ServiceFactory<
|
||||||
TcpStream,
|
TcpStream,
|
||||||
Config = (),
|
Config = (),
|
||||||
|
@ -306,7 +360,11 @@ mod rustls {
|
||||||
protos.extend_from_slice(&config.alpn_protocols);
|
protos.extend_from_slice(&config.alpn_protocols);
|
||||||
config.alpn_protocols = protos;
|
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(|_| {
|
.map_init_err(|_| {
|
||||||
unreachable!("TLS acceptor service factory does not error on init")
|
unreachable!("TLS acceptor service factory does not error on init")
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
|
|
||||||
extern crate tls_openssl as openssl;
|
extern crate tls_openssl as openssl;
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
use std::{convert::Infallible, io};
|
use std::{convert::Infallible, io};
|
||||||
|
|
||||||
use actix_http::{
|
use actix_http::{
|
||||||
body::{BodyStream, BoxBody, SizedStream},
|
body::{BodyStream, BoxBody, SizedStream},
|
||||||
error::PayloadError,
|
error::PayloadError,
|
||||||
header::{self, HeaderValue},
|
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_http_test::test_server;
|
||||||
use actix_service::{fn_service, ServiceFactoryExt};
|
use actix_service::{fn_service, ServiceFactoryExt};
|
||||||
|
@ -89,7 +90,10 @@ async fn h2_1() -> io::Result<()> {
|
||||||
assert_eq!(req.version(), Version::HTTP_2);
|
assert_eq!(req.version(), Version::HTTP_2);
|
||||||
ok::<_, Error>(Response::ok())
|
ok::<_, Error>(Response::ok())
|
||||||
})
|
})
|
||||||
.openssl(tls_config())
|
.openssl_with_config(
|
||||||
|
tls_config(),
|
||||||
|
TlsAcceptorConfig::new(Some(Duration::from_secs(5))),
|
||||||
|
)
|
||||||
.map_err(|_| ())
|
.map_err(|_| ())
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
- Add `Route::wrap()` to allow individual routes to use middleware. [#2725]
|
- Add `Route::wrap()` to allow individual routes to use middleware. [#2725]
|
||||||
- Add `ServiceConfig::default_service()`. [#2338] [#2743]
|
- Add `ServiceConfig::default_service()`. [#2338] [#2743]
|
||||||
- Implement `ResponseError` for `std::convert::Infallible`
|
- Implement `ResponseError` for `std::convert::Infallible`
|
||||||
|
- Add `tls_handshake_timeout` server configuration option to configure TLS handshake timeout [#2752]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Clear connection-level data on `HttpRequest` drop. [#2742]
|
- Clear connection-level data on `HttpRequest` drop. [#2742]
|
||||||
|
|
|
@ -18,6 +18,9 @@ use actix_tls::accept::openssl::reexports::{AlpnError, SslAcceptor, SslAcceptorB
|
||||||
#[cfg(feature = "rustls")]
|
#[cfg(feature = "rustls")]
|
||||||
use actix_tls::accept::rustls::reexports::ServerConfig as RustlsServerConfig;
|
use actix_tls::accept::rustls::reexports::ServerConfig as RustlsServerConfig;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "openssl", feature = "rustls"))]
|
||||||
|
use actix_http::TlsAcceptorConfig;
|
||||||
|
|
||||||
use crate::{config::AppConfig, Error};
|
use crate::{config::AppConfig, Error};
|
||||||
|
|
||||||
struct Socket {
|
struct Socket {
|
||||||
|
@ -30,6 +33,8 @@ struct Config {
|
||||||
keep_alive: KeepAlive,
|
keep_alive: KeepAlive,
|
||||||
client_request_timeout: Duration,
|
client_request_timeout: Duration,
|
||||||
client_disconnect_timeout: Duration,
|
client_disconnect_timeout: Duration,
|
||||||
|
#[cfg(any(feature = "openssl", feature = "rustls"))]
|
||||||
|
tls_handshake_timeout: Option<Duration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An HTTP Server.
|
/// An HTTP Server.
|
||||||
|
@ -92,6 +97,8 @@ where
|
||||||
keep_alive: KeepAlive::default(),
|
keep_alive: KeepAlive::default(),
|
||||||
client_request_timeout: Duration::from_secs(5),
|
client_request_timeout: Duration::from_secs(5),
|
||||||
client_disconnect_timeout: Duration::from_secs(1),
|
client_disconnect_timeout: Duration::from_secs(1),
|
||||||
|
#[cfg(any(feature = "rustls", feature = "openssl"))]
|
||||||
|
tls_handshake_timeout: None,
|
||||||
})),
|
})),
|
||||||
backlog: 1024,
|
backlog: 1024,
|
||||||
sockets: Vec::new(),
|
sockets: Vec::new(),
|
||||||
|
@ -225,6 +232,22 @@ where
|
||||||
self
|
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)]
|
#[doc(hidden)]
|
||||||
#[deprecated(since = "4.0.0", note = "Renamed to `client_disconnect_timeout`.")]
|
#[deprecated(since = "4.0.0", note = "Renamed to `client_disconnect_timeout`.")]
|
||||||
pub fn client_shutdown(self, dur: u64) -> Self {
|
pub fn client_shutdown(self, dur: u64) -> Self {
|
||||||
|
@ -379,7 +402,10 @@ where
|
||||||
svc.finish(map_config(fac, move |_| {
|
svc.finish(map_config(fac, move |_| {
|
||||||
AppConfig::new(true, host.clone(), addr)
|
AppConfig::new(true, host.clone(), addr)
|
||||||
}))
|
}))
|
||||||
.openssl(acceptor.clone())
|
.openssl_with_config(
|
||||||
|
acceptor.clone(),
|
||||||
|
TlsAcceptorConfig::new(c.tls_handshake_timeout),
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
@ -437,7 +463,10 @@ where
|
||||||
svc.finish(map_config(fac, move |_| {
|
svc.finish(map_config(fac, move |_| {
|
||||||
AppConfig::new(true, host.clone(), addr)
|
AppConfig::new(true, host.clone(), addr)
|
||||||
}))
|
}))
|
||||||
.rustls(config.clone())
|
.rustls_with_config(
|
||||||
|
config.clone(),
|
||||||
|
TlsAcceptorConfig::new(c.tls_handshake_timeout),
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
|
Loading…
Reference in New Issue