mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-16 02:26:54 +00:00
[MEDIUM] extract the HTTP tarpit code from process_request().
The tarpit is now an autonomous independant analyser.
This commit is contained in:
parent
edcf6687d6
commit
60b85b0694
@ -63,6 +63,7 @@ int process_cli(struct session *t);
|
|||||||
int process_srv_data(struct session *t);
|
int process_srv_data(struct session *t);
|
||||||
int process_srv_conn(struct session *t);
|
int process_srv_conn(struct session *t);
|
||||||
int process_request(struct session *t);
|
int process_request(struct session *t);
|
||||||
|
int http_process_tarpit(struct session *s, struct buffer *req);
|
||||||
int process_response(struct session *t);
|
int process_response(struct session *t);
|
||||||
|
|
||||||
int produce_content(struct session *s);
|
int produce_content(struct session *s);
|
||||||
|
@ -2359,42 +2359,6 @@ int process_request(struct session *t)
|
|||||||
; // to keep gcc happy
|
; // to keep gcc happy
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->analysers & AN_REQ_HTTP_TARPIT) {
|
|
||||||
struct http_txn *txn = &t->txn;
|
|
||||||
|
|
||||||
/* This connection is being tarpitted. The CLIENT side has
|
|
||||||
* already set the connect expiration date to the right
|
|
||||||
* timeout. We just have to check that the client is still
|
|
||||||
* there and that the timeout has not expired.
|
|
||||||
*/
|
|
||||||
if ((req->flags & (BF_SHUTR|BF_READ_ERROR)) == 0 &&
|
|
||||||
!tick_is_expired(req->analyse_exp, now_ms))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* We will set the queue timer to the time spent, just for
|
|
||||||
* logging purposes. We fake a 500 server error, so that the
|
|
||||||
* attacker will not suspect his connection has been tarpitted.
|
|
||||||
* It will not cause trouble to the logs because we can exclude
|
|
||||||
* the tarpitted connections by filtering on the 'PT' status flags.
|
|
||||||
*/
|
|
||||||
trace_term(t, TT_HTTP_SRV_2);
|
|
||||||
t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
|
|
||||||
|
|
||||||
txn->status = 500;
|
|
||||||
if (req->flags != BF_READ_ERROR)
|
|
||||||
stream_int_retnclose(req->prod, error_message(t, HTTP_ERR_500));
|
|
||||||
|
|
||||||
req->analysers = 0;
|
|
||||||
req->analyse_exp = TICK_ETERNITY;
|
|
||||||
|
|
||||||
t->fe->failed_req++;
|
|
||||||
if (!(t->flags & SN_ERR_MASK))
|
|
||||||
t->flags |= SN_ERR_PRXCOND;
|
|
||||||
if (!(t->flags & SN_FINST_MASK))
|
|
||||||
t->flags |= SN_FINST_T;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req->analysers & AN_REQ_HTTP_BODY) {
|
if (req->analysers & AN_REQ_HTTP_BODY) {
|
||||||
/* We have to parse the HTTP request body to find any required data.
|
/* We have to parse the HTTP request body to find any required data.
|
||||||
* "balance url_param check_post" should have been the only way to get
|
* "balance url_param check_post" should have been the only way to get
|
||||||
@ -2484,6 +2448,47 @@ int process_request(struct session *t)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function is an analyser which processes the HTTP tarpit. It always
|
||||||
|
* returns zero, at the beginning because it prevents any other processing
|
||||||
|
* from occurring, and at the end because it terminates the request.
|
||||||
|
*/
|
||||||
|
int http_process_tarpit(struct session *s, struct buffer *req)
|
||||||
|
{
|
||||||
|
struct http_txn *txn = &s->txn;
|
||||||
|
|
||||||
|
/* This connection is being tarpitted. The CLIENT side has
|
||||||
|
* already set the connect expiration date to the right
|
||||||
|
* timeout. We just have to check that the client is still
|
||||||
|
* there and that the timeout has not expired.
|
||||||
|
*/
|
||||||
|
if ((req->flags & (BF_SHUTR|BF_READ_ERROR)) == 0 &&
|
||||||
|
!tick_is_expired(req->analyse_exp, now_ms))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* We will set the queue timer to the time spent, just for
|
||||||
|
* logging purposes. We fake a 500 server error, so that the
|
||||||
|
* attacker will not suspect his connection has been tarpitted.
|
||||||
|
* It will not cause trouble to the logs because we can exclude
|
||||||
|
* the tarpitted connections by filtering on the 'PT' status flags.
|
||||||
|
*/
|
||||||
|
trace_term(s, TT_HTTP_SRV_2);
|
||||||
|
s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
|
||||||
|
|
||||||
|
txn->status = 500;
|
||||||
|
if (req->flags != BF_READ_ERROR)
|
||||||
|
stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_500));
|
||||||
|
|
||||||
|
req->analysers = 0;
|
||||||
|
req->analyse_exp = TICK_ETERNITY;
|
||||||
|
|
||||||
|
s->fe->failed_req++;
|
||||||
|
if (!(s->flags & SN_ERR_MASK))
|
||||||
|
s->flags |= SN_ERR_PRXCOND;
|
||||||
|
if (!(s->flags & SN_FINST_MASK))
|
||||||
|
s->flags |= SN_FINST_T;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* This function performs all the processing enabled for the current response.
|
/* This function performs all the processing enabled for the current response.
|
||||||
* It normally returns zero, but may return 1 if it absolutely needs to be
|
* It normally returns zero, but may return 1 if it absolutely needs to be
|
||||||
* called again after other functions. It relies on buffers flags, and updates
|
* called again after other functions. It relies on buffers flags, and updates
|
||||||
|
@ -709,6 +709,10 @@ resync_stream_interface:
|
|||||||
if (!process_request(s))
|
if (!process_request(s))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (s->req->analysers & AN_REQ_HTTP_TARPIT)
|
||||||
|
if (!http_process_tarpit(s, s->req))
|
||||||
|
break;
|
||||||
|
|
||||||
/* Just make sure that nobody set a wrong flag causing an endless loop */
|
/* Just make sure that nobody set a wrong flag causing an endless loop */
|
||||||
s->req->analysers &= AN_REQ_INSPECT | AN_REQ_HTTP_HDR | AN_REQ_HTTP_TARPIT | AN_REQ_HTTP_BODY;
|
s->req->analysers &= AN_REQ_INSPECT | AN_REQ_HTTP_HDR | AN_REQ_HTTP_TARPIT | AN_REQ_HTTP_BODY;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user