-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
fix(server): start header read timeout immediately #3185
Conversation
f46fc9f
to
36a24e7
Compare
I ran into this Today. Anything blocking this? |
A comment on the linked issue gave me pause. I started looking in other libraries, and for instance in Go, they use a cc @sfackler, you've asked often about idle and read timeouts. |
I would interpret the time before the first byte of the header is read as idle time rather than read-header time, yeah. You can already make a wrapper around a Hyper Connection + handler service that tracks idle timeouts but it's a huge PITA. Having a built in feature for that would definitely be a good idea given that it's a pretty universal thing to want in servers. |
FWIW the documentation on
+1 to using the same timeout such that a longer time budget helps both idle connections and slow header connections but does not help malicious connections (which idle and then slowly send headers) last twice as long. |
I forgot about this and made my own PR. Without this change, hyper is vulnerable to malicious actors who may just open connections and never send anything. I'd love a idle timeout functionality, but that's a lot more involved afaict. To be honest, I was planning on just using this "fixed" header timeout behaviour in addition to a "idle timeout" in my Reading headers is the very first stage of a new HTTP 1 connection and it makes sense to me that it would timeout if |
Would a different config please everybody? Maybe |
I think, from talking to several people, many find it clearer for there to be a separate timeout. So yea, something like |
This is a restatement of #3185 (comment) with additional details.
Clarity aside, isn't it the case that splitting one timeout into two timeouts could make DoS twice as effective? For example, assume 99.99% of legitimate clients will send a header consisting of multiple TCP segments, and may occasionally experience up to 5000ms of latency/congestion e.g. due to being on a cellular data connection. If there was one timeout, it could be 5000ms. As such, an adversary must transmit the entire header in 4750ms for a good chance keeping the connection open. If there were two timeouts, both of them would have to be 5000ms, because the congestion could occur either before or during the header transmission. As such, an adversary could wait 4750ms before sending the first segment and then an additional 4750ms before sending the rest of the header, keeping the connection open for twice as long. By Little's Law, doubling the lifetime of a connection means there will be double the number of active connections, per unit of potentially-firewall-limited adversary bandwidth. This could double the impact of a DoS attack on OS and server process resources. (that said, having a timeout is infinitely better than not having one. the two-timeout approach is probably good enough for me) |
c787877
to
534a1f6
Compare
The `http1_header_read_timeout` used to start once there was a single read of headers. This change makes it start the timer immediately, right when the connection is estabilished.
534a1f6
to
25a4abf
Compare
I've since decided to re-open this and merge. While some libraries do have a separate timeout options, none of them seem to use the idle timeout for the very first request. Any concern of a browser preconnect not working isn't a concern to any other implementation, and that makes sense: if a browser looks like a bad guy, it should stop that. |
Hello everyone, sorry to bother you. If I connect with nc and do nothing for 10 sec or if I start pressing enter without typing anything, the connection is closed after 10 sec. If I send a request and, after receiving the reply, press enter again, the connection is closed after 10 sec. But it will never be closed if I send a request and do nothing after receiving the reply, leaving the connection open and inactive. Is this normal behaviour? Shouldn't it still be closed by the server after 10 sec? Thanks in advance. |
|
Interesting. Could you open a new issue with a reproduction so we can look into it? |
Maybe I'm understanding wrong, but I think this is working as designed. If you press enter, then you're sending a new request and at that point the header read timeout starts ticking. If you want connections to be closed after a request is done, then that's probably new code to handle that or different settings? What if you send |
Ah, yes. I was confused (see #3743 (comment) for more). The current behavior only starts the header read timeout once a subsequent request has already been started. The linked comment shows a simple change that would change this. This PR will, if merged, apply the h1 header timeout when waiting for subsequent requests, closing the gap between expectations and actual behavior here: #3828
This new test is a reproducible example: 1ed8ea0 |
I think that #3828 describes perfectly the situation: "after the first request, the connection can remain open indefinitely". So if the change proposed in the PR solves this problem, we should be fine.
I totally agree with what you said here.
But the behaviour I would like is not to close the connection after each request. This can be achieved by deactivating keep_alive with the dedicated function of the server's Builder. What I would like is for there to be a timeout that tells the server when to close the connection if it remains idle after a request. Which is exactly the behaviour described for what was called ‘idle_timeout’ in the quoted PR. I apologise if I misspoke above, what I was wondering was whether it was normal for the timeout set with header_request_timeout() to fail during an idle period after a request has been sent.
If it can still be useful, I'm working with hyper version 1.5.1. Thank you all for your time. |
Good morning! When do you think the pull request for this problem will be reviewed and possibly accepted? |
The
http1_header_read_timeout
used to start once there was a single read of headers. This change makes it start the timer immediately, right when the connection is estabilished.Closes #3178
cc @paolobarbolini @silence-coding @SylvainGarrigues