You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

82 lines
3.5 KiB

  1. From 294e4676a3b775a7accb50eb8428f293c218b5e2 Mon Sep 17 00:00:00 2001
  2. From: Willy Tarreau <w@1wt.eu>
  3. Date: Mon, 11 May 2015 18:30:33 +0200
  4. Subject: [PATCH 2/2] BUG/MEDIUM: http: don't forward client shutdown without
  5. NOLINGER except for tunnels
  6. There's an issue related with shutting down POST transfers or closing the
  7. connection after the end of the upload : the shutdown is forwarded to the
  8. server regardless of the abortonclose option. The problem it causes is that
  9. during a scan, brute force or whatever, it becomes possible that all source
  10. ports are exhausted with all sockets in TIME_WAIT state.
  11. There are multiple issues at once in fact :
  12. - no action is done for the close, it automatically happens at the lower
  13. layers thanks for channel_auto_close(), so we cannot act on NOLINGER ;
  14. - we *do* want to continue to send a clean shutdown in tunnel mode because
  15. some protocols transported over HTTP may need this, regardless of option
  16. abortonclose, thus we can't set the option inconditionally
  17. - for all other modes, we do want to close the dirty way because we're
  18. certain whether we've sent everything or not, and we don't want to eat
  19. all source ports.
  20. The solution is a bit complex and applies to DONE/TUNNEL states :
  21. 1) disable automatic close for everything not a tunnel and not just
  22. keep-alive / server-close. Force-close is now covered, as is HTTP/1.0
  23. which implicitly works in force-close mode ;
  24. 2) when processing option abortonclose, we know we can disable lingering
  25. if the client has closed and the connection is not in tunnel mode.
  26. Since the last case above leads to a situation where the client side reports
  27. an error, we know the connection will not be reused, so leaving the flag on
  28. the stream-interface is safe. A client closing in the middle of the data
  29. transmission already aborts the transaction so this case is not a problem.
  30. This fix must be backported to 1.5 where the problem was detected.
  31. (cherry picked from commit bbfb6c40854925367ae5f9e8b22c5c9a18dc69d5)
  32. ---
  33. src/proto_http.c | 14 ++++++++++----
  34. 1 file changed, 10 insertions(+), 4 deletions(-)
  35. diff --git a/src/proto_http.c b/src/proto_http.c
  36. index 0ac3a47..5db64b5 100644
  37. --- a/src/proto_http.c
  38. +++ b/src/proto_http.c
  39. @@ -5452,9 +5452,10 @@ int http_request_forward_body(struct session *s, struct channel *req, int an_bit
  40. msg->sov -= msg->next;
  41. msg->next = 0;
  42. - /* for keep-alive we don't want to forward closes on DONE */
  43. - if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
  44. - (txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_SCL)
  45. + /* we don't want to forward closes on DONE except in
  46. + * tunnel mode.
  47. + */
  48. + if ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN)
  49. channel_dont_close(req);
  50. if (http_resync_states(s)) {
  51. /* some state changes occurred, maybe the analyser
  52. @@ -5478,10 +5479,15 @@ int http_request_forward_body(struct session *s, struct channel *req, int an_bit
  53. * want to monitor the client's connection and forward
  54. * any shutdown notification to the server, which will
  55. * decide whether to close or to go on processing the
  56. - * request.
  57. + * request. We only do that in tunnel mode, and not in
  58. + * other modes since it can be abused to exhaust source
  59. + * ports.
  60. */
  61. if (s->be->options & PR_O_ABRT_CLOSE) {
  62. channel_auto_read(req);
  63. + if ((req->flags & (CF_SHUTR|CF_READ_NULL)) &&
  64. + ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN))
  65. + s->si[1].flags |= SI_FL_NOLINGER;
  66. channel_auto_close(req);
  67. }
  68. else if (s->txn.meth == HTTP_METH_POST) {
  69. --
  70. 2.0.5