Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report timeouts as Errors, with original connection (AsyncAccept::Connection) #36

Closed
ahcodedthat opened this issue Sep 20, 2023 · 2 comments · Fixed by #37
Closed

Report timeouts as Errors, with original connection (AsyncAccept::Connection) #36

ahcodedthat opened this issue Sep 20, 2023 · 2 comments · Fixed by #37

Comments

@ahcodedthat
Copy link
Contributor

Currently, when a TLS handshake times out, the connection is closed silently. It would probably be better to report these events to the application as a new variant of tls_listener::Error, containing the original connection object (AsyncAccept::Connection), so that the application can fetch the client's IP address (using TcpStream::peer_addr) and emit a log message.

That way, if an attacker attempts to DoS the application by opening a lot of dummy connections, thus exceeding max_handshakes, the log messages will tell the administrator what's going on and what the attacker's IP addresses are.

tmccombs added a commit that referenced this issue Sep 21, 2023
And make the errors enun non_exhaustive

BREAKING CHANGE: Adds a new variant to the Error Enum
BREAKING CHANGE: The Error enum is now non_exhaustive
BREAKING CHANGE: Now returns an error if a handshake times out
Fixes: #36
@tmccombs
Copy link
Owner

It would probably be better to report these events to the application as a new variant of tls_listener::Error

this would be pretty straightforward to do, although it would break backwards compatibility.

containing the original connection object (AsyncAccept::Connection)

This is more difficult. By the time we get a timeout the connection is owned by the future that is performing the handshake, and I no longer have any reference to it. Furthermore, I don't even have access to the actual Future, since I pull from a FuturesUnordered stream.

As a possible workaround, you could do the following:

  1. Create a your own wrapper type that implements AsyncTls and wraps one of the existing implementations
  2. In the accept method, capture the peer_addr or any other information of interest, and return a new Future that includes that data alongside the underlying Future, and have some way to track if the handshake completed. (such as a boolean, using an enum, calling a method on the inner future, etc.)
  3. impl Drop on your type, check if the inner future has completed, and if not log the associated information.

If you have any good ideas on how I could include the connection or information about the connection, I would be happy to hear them.

tmccombs added a commit that referenced this issue Sep 21, 2023
And make the errors enun non_exhaustive

BREAKING CHANGE: Adds a new variant to the Error Enum
BREAKING CHANGE: The Error enum is now non_exhaustive
BREAKING CHANGE: Now returns an error if a handshake times out
Fixes: #36
@ahcodedthat
Copy link
Contributor Author

ahcodedthat commented Sep 23, 2023

Ah, you're right. Although tokio_openssl does allow aborting the handshake and taking back the SslStream, the other two TLS libraries take ownership of the socket during the handshake, making it impossible to abort the handshake without also closing the socket.

I've submitted #38 as an alternative. Instead of giving back the socket upon error, that PR changes AsyncAccept and TlsListener to report the remote address, both on error and on success. What do you think of that idea?

tmccombs added a commit that referenced this issue Sep 28, 2023
And make the errors enun non_exhaustive

BREAKING CHANGE: Adds a new variant to the Error Enum
BREAKING CHANGE: The Error enum is now non_exhaustive
BREAKING CHANGE: Now returns an error if a handshake times out
Fixes: #36
tmccombs added a commit that referenced this issue Oct 16, 2023
This now exposes the address of the peer connection both when accepting
a new connection, and included in error variants.

Unfortunately, this required several breaking changes.

BREAKING CHANGE: AsyncAccept::poll_accept now returns a pair of the
connection and address
BREAKING CHANGE: AsyncAccept now has an Address associated type
BREAKING CHANGE: Error now has an additional type parameter
BREAKING CHANGE: AsyncAccept::Error must implement std::error::Error
BREAKING CHANGE: TlsAcceptError is now a struct form variant.
Fixes: #36
Co-authored-by: ahcodedthat
tmccombs added a commit that referenced this issue Oct 17, 2023
This builds on the previous commit. In addition to some minor stylictic
and naming changes (such as calling the address peer_addr instead of
remote_addr to be more consistent with tokio and stdlib), the main
change here is replacing the FutureWithExtraData with a more
purpose-built Waiting struct encodes the state of a connection that is
waitinf for a handshake to complete.

BREAKING CHANGE: AsyncAccept::Error must implement std::error::Error
BREAKING CHANGE: TlsAcceptError is now a struct form variant.
Fixes: #36
tmccombs added a commit that referenced this issue Oct 17, 2023
This builds on the previous commit. In addition to some minor stylictic
and naming changes (such as calling the address peer_addr instead of
remote_addr to be more consistent with tokio and stdlib), the main
change here is replacing the FutureWithExtraData with a more
purpose-built Waiting struct encodes the state of a connection that is
waitinf for a handshake to complete.

BREAKING CHANGE: AsyncAccept::Error must implement std::error::Error
BREAKING CHANGE: TlsAcceptError is now a struct form variant.
Fixes: #36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants