[MEDIUM] extract the HTTP tarpit code from process_request().

The tarpit is now an autonomous independant analyser.
This commit is contained in:
Willy Tarreau 2008-11-30 23:28:40 +01:00
parent edcf6687d6
commit 60b85b0694
3 changed files with 46 additions and 36 deletions

View File

@ -63,6 +63,7 @@ int process_cli(struct session *t);
int process_srv_data(struct session *t);
int process_srv_conn(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 produce_content(struct session *s);

View File

@ -2359,42 +2359,6 @@ int process_request(struct session *t)
; // 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) {
/* 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
@ -2484,6 +2448,47 @@ int process_request(struct session *t)
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.
* 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

View File

@ -709,6 +709,10 @@ resync_stream_interface:
if (!process_request(s))
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 */
s->req->analysers &= AN_REQ_INSPECT | AN_REQ_HTTP_HDR | AN_REQ_HTTP_TARPIT | AN_REQ_HTTP_BODY;