mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-05 10:58:14 +00:00
BUG/MEDIUM: http: don't forward client shutdown without NOLINGER except for tunnels
There's an issue related with shutting down POST transfers or closing the connection after the end of the upload : the shutdown is forwarded to the server regardless of the abortonclose option. The problem it causes is that during a scan, brute force or whatever, it becomes possible that all source ports are exhausted with all sockets in TIME_WAIT state. There are multiple issues at once in fact : - no action is done for the close, it automatically happens at the lower layers thanks for channel_auto_close(), so we cannot act on NOLINGER ; - we *do* want to continue to send a clean shutdown in tunnel mode because some protocols transported over HTTP may need this, regardless of option abortonclose, thus we can't set the option inconditionally - for all other modes, we do want to close the dirty way because we're certain whether we've sent everything or not, and we don't want to eat all source ports. The solution is a bit complex and applies to DONE/TUNNEL states : 1) disable automatic close for everything not a tunnel and not just keep-alive / server-close. Force-close is now covered, as is HTTP/1.0 which implicitly works in force-close mode ; 2) when processing option abortonclose, we know we can disable lingering if the client has closed and the connection is not in tunnel mode. Since the last case above leads to a situation where the client side reports an error, we know the connection will not be reused, so leaving the flag on the stream-interface is safe. A client closing in the middle of the data transmission already aborts the transaction so this case is not a problem. This fix must be backported to 1.5 where the problem was detected.
This commit is contained in:
parent
82ff3c9b05
commit
bbfb6c4085
@ -5648,9 +5648,10 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
msg->sov -= msg->next;
|
||||
msg->next = 0;
|
||||
|
||||
/* for keep-alive we don't want to forward closes on DONE */
|
||||
if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
|
||||
(txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL)
|
||||
/* we don't want to forward closes on DONE except in
|
||||
* tunnel mode.
|
||||
*/
|
||||
if ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN)
|
||||
channel_dont_close(req);
|
||||
if (http_resync_states(s)) {
|
||||
/* some state changes occurred, maybe the analyser
|
||||
@ -5674,10 +5675,15 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
* want to monitor the client's connection and forward
|
||||
* any shutdown notification to the server, which will
|
||||
* decide whether to close or to go on processing the
|
||||
* request.
|
||||
* request. We only do that in tunnel mode, and not in
|
||||
* other modes since it can be abused to exhaust source
|
||||
* ports.
|
||||
*/
|
||||
if (s->be->options & PR_O_ABRT_CLOSE) {
|
||||
channel_auto_read(req);
|
||||
if ((req->flags & (CF_SHUTR|CF_READ_NULL)) &&
|
||||
((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN))
|
||||
s->si[1].flags |= SI_FL_NOLINGER;
|
||||
channel_auto_close(req);
|
||||
}
|
||||
else if (s->txn->meth == HTTP_METH_POST) {
|
||||
|
Loading…
Reference in New Issue
Block a user