Skip to content

Acceptor timeout config #4

Closed
Closed

Description

@vasilakisfil

Is there a way to limit how much time the acceptor is going to wait for the TLS handshake to take place from the client side? If a malicious client never sends its TLS handshake request part, will this block forever?

If yes then probably the example should be updated to use tokio's timeout.

Activity

  1. rfarr commented on Jul 20, 2023

    @rfarr

    @vasilakisfil This is how I've done it. The key is to not await on the accept() call but instead wrap that future in the tokio timeout.

    let tls_config = rustls::ServerConfig::builder()
        .with_safe_defaults()
        .with_no_client_auth()
        .with_single_cert(certs, private_key)
        .unwrap();
    
    let tls_acceptor = tokio_rustls::TlsAcceptor::from(tls_config);
    
    // ...
    // Inside the acceptor loop after you have a tcp connection already accepted
    // ...
    
    let tls_stream = tls_acceptor.accept(tcp_stream).map_err(|e| {
        std::io::Error::new(std::io::ErrorKind::Other, format!("Client TLS connect fail: {:?}", e))
    });
    
    // Wrap the accept future with a timeout to put an upper limit on how long a client can take to complete
    // the TLS handshake and get to a TLS "connected" state
    let tls_handshake_timeout_seconds: u8 = 5;
    let tls_stream = tokio::time::timeout(tokio::time::Duration::from_secs(tls_handshake_timeout_seconds.into()), tls_stream).map_err(move |_e| {
      std::io::Error::new(std::io::ErrorKind::TimedOut, format!("Client TLS handshake timeout after {} seconds", tls_handshake_timeout_seconds))
     });
     
    let tls_stream = match tls_stream.await {
        // Happy path
        Ok(tls_stream) => tls_stream,
        // Some kind of error
        Err(e) => ...
        // Timeout
        Ok(Err(e)) => ...
    };
  2. vasilakisfil commented on Jul 21, 2023

    @vasilakisfil
    Author

    Thanks, yes I have done the same thing. On event-driven architectures (aka channels), not having a timeout limit by default can lead to serious unexpected stalls in an application. Probably it's a good idea to add something on the documentation about it.

  3. nirbheek commented on Dec 11, 2023

    @nirbheek

    This seems like a serious issue to me, the lack of a TLS timeout means that applications built on tokio-rustls are vulnerable out of the box to a DoS attack to exhaust FDs, like a very basic Slowloris attack but with TLS.

    I think by default there should be an aggressive configurable timeout for completion of the TLS handshake.

    You can do a DoS on the default rustls server example by just spawning tons of nc <host> <port> instances that will never, ever timeout.

  4. Congyuwang commented on Jul 11, 2024

    @Congyuwang

    I think this is indeed quite needed! I find my server with a lot of ESTABLISHED connection with 0/0 bytes communication that hangs forever, even though I have a timeout layer in my Axum service. It turns out that these connections await at tls_acceptor.accept(stream).await.

  5. djc commented on Dec 11, 2024

    @djc
    Member

    (Make sure to also take care of the LazyConfigAcceptor when we tackle this.)

  6. stormshield-gt commented on Jan 13, 2025

    @stormshield-gt

    Just to mention it, another solution is to put the application behind a reverse proxy, as it was the general wisdom in the early days of Go.

  7. Congyuwang commented on Jan 13, 2025

    @Congyuwang

    Just to mention it, another solution is to put the application behind a reverse proxy, as it was the general wisdom in the early days of Go.

    That’s a good idea.

  8. cpu commented on Jul 20, 2026

    @cpu
    Member

    If yes then probably the example should be updated to use tokio's timeout.

    See #187

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions