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

Defends against slow HTTP attacks. #2457

Closed
silence-coding opened this issue Mar 10, 2021 · 5 comments · Fixed by #2675
Closed

Defends against slow HTTP attacks. #2457

silence-coding opened this issue Mar 10, 2021 · 5 comments · Fixed by #2675
Labels
A-server Area: server. C-feature Category: feature. This is adding a new feature.

Comments

@silence-coding
Copy link
Contributor

I think hyper needs to add capabilities such as client_header_timeout and client_body_timeout to defend against slow attacks.

The Nginx defense method is as follows:
https://www.nginx.com/blog/mitigating-ddos-attacks-with-nginx-and-nginx-plus/#client_header_timeout

@davidpdrsn davidpdrsn added A-server Area: server. C-feature Category: feature. This is adding a new feature. labels May 7, 2021
seanmonstar pushed a commit that referenced this issue Nov 18, 2021
Adds `Server::http1_header_read_timeout(Duration)`. Setting a duration will determine how long a client has to finish sending all the request headers before trigger a timeout test. This can help reduce resource usage when bad actors open connections without sending full requests.

Closes #2457
@mjbshaw
Copy link

mjbshaw commented Nov 22, 2021

Should #2675 have fully closed this? Seems like the second half of this issue is client_body_timeout, which is still unimplemented.

@seanmonstar
Copy link
Member

I believe a user can handle a body timeout outside of a hyper, since you can add a timeout to any waiting on a body chunk. Is there something specific about it that hyper would need to do directly?

@mjbshaw
Copy link

mjbshaw commented Nov 22, 2021

Yeah, that should be sufficient. Sorry; when I read #2675 I noticed it said it partially addressed this issue, and that this issue's second half was client_body_timeout. But you're right. Thanks!

@DFINITYManu
Copy link

DFINITYManu commented Aug 5, 2023

PR #2675 does not actually defend against slowloris attacks. From my comment there:

Valiant effort, but still there is no way to set a timeout for clients that connect only to send no data (by experimentation I discovered that the timeout does not fire if I just telnet into the TCP port and hang on there -- it only fires if I send the actual headers too late). Which means it's trivial to gum up a hyper server just by sending a lot of connections and nothing else.

What is needed is an actual "you sent no data over this period of time? close socket" timeout, and this should also be implemented for HTTP/2/3. There is a timeout field in https://recursion.wtf/embed-wasm/hyper/server/conn/struct.AddrIncoming.html but there is no way for the user to set it. Egads, the server socket is not closed until the client finally sends some data too late -- which is not how a massive open socket attack is going to go.

This issue ought to be reopened.

@jeromegn
Copy link

jeromegn commented Sep 5, 2023

What is needed is an actual "you sent no data over this period of time? close socket" timeout, and this should also be implemented for HTTP/2/3

That's kind of hard, there are many things to take into account. For example:

  • If you're proxying, then there's a race between the 2 idle timeouts if they're the same.
  • The kernel buffers data that won't be immediately available in poll* functions (they'll receive a Poll::Pending even if there was actual data transmitted). So to figure it out, you also need to look at the tcpinfo struct you can get by doing a syscall and see how much data is "notsent". This adds blockage to normally non-blocking tasks. Even for a very short time, it can build up if you're handling a lot of connections.
  • For HTTP2/3, multiple requests can happen on the same connection, at the same time. It could be possible to close a whole connection if any client request takes too long to send its headers, but would that be desirable? That would break all other ongoing HTTP requests for the same connection.

There is a timeout field in https://recursion.wtf/embed-wasm/hyper/server/conn/struct.AddrIncoming.html but there is no way for the user to set it.

That looks like the timeout for when accepting fails (usually due to "too many open files"). It's set to a sleep w/ a duration of 1 second when an error happens, when it has elapsed, it is removed.

Edit: I'm facing similar issues btw, I just thought I'd share my experience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-server Area: server. C-feature Category: feature. This is adding a new feature.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants