[MEDIUM] introduce "timeout http-request" in frontends
In order to offer DoS protection, it may be required to lower the maximum accepted time to receive a complete HTTP request without affecting the client timeout. This helps protecting against established connections on which nothing is sent. The client timeout cannot offer a good protection against this abuse because it is an inactivity timeout, which means that if the attacker sends one character every now and then, the timeout will not trigger. With the HTTP request timeout, no matter what speed the client types, the request will be aborted if it does not complete in time.
This commit is contained in:
parent
a0250ba38d
commit
036fae0ec9
@ -603,6 +603,7 @@ timeout client X X X -
|
||||
timeout clitimeout X X X - (deprecated)
|
||||
timeout connect X - X X
|
||||
timeout contimeout X - X X (deprecated)
|
||||
timeout httpreq X X X -
|
||||
timeout queue X - X X
|
||||
timeout server X - X X
|
||||
timeout srvtimeout X - X X (deprecated)
|
||||
@ -952,7 +953,8 @@ clitimeout <timeout>
|
||||
This parameter is provided for compatibility but is currently deprecated.
|
||||
Please use "timeout client" instead.
|
||||
|
||||
See also : "timeout client", "timeout server", "srvtimeout".
|
||||
See also : "timeout client", "timeout http-request", "timeout server", and
|
||||
"srvtimeout".
|
||||
|
||||
|
||||
contimeout <timeout>
|
||||
@ -2060,6 +2062,40 @@ timeout contimeout <timeout> (deprecated)
|
||||
See also : "timeout queue", "timeout server", "contimeout".
|
||||
|
||||
|
||||
timeout http-request <timeout>
|
||||
Set the maximum allowed time to wait for a complete HTTP request
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
yes | yes | yes | no
|
||||
Arguments :
|
||||
<timeout> is the timeout value is specified in milliseconds by default, but
|
||||
can be in any other unit if the number is suffixed by the unit,
|
||||
as explained at the top of this document.
|
||||
|
||||
In order to offer DoS protection, it may be required to lower the maximum
|
||||
accepted time to receive a complete HTTP request without affecting the client
|
||||
timeout. This helps protecting against established connections on which
|
||||
nothing is sent. The client timeout cannot offer a good protection against
|
||||
this abuse because it is an inactivity timeout, which means that if the
|
||||
attacker sends one character every now and then, the timeout will not
|
||||
trigger. With the HTTP request timeout, no matter what speed the client
|
||||
types, the request will be aborted if it does not complete in time.
|
||||
|
||||
Note that this timeout only applies to the header part of the request, and
|
||||
not to any data. As soon as the empty line is received, this timeout is not
|
||||
used anymore.
|
||||
|
||||
Generally it is enough to set it to a few seconds, as most clients send the
|
||||
full request immediately upon connection. Add 3 or more seconds to cover TCP
|
||||
retransmits but that's all. Setting it to very low values (eg: 50 ms) will
|
||||
generally work on local networks as long as there are no packet losses. This
|
||||
will prevent people from sending bare HTTP requests using telnet.
|
||||
|
||||
If this parameter is not set, the client timeout still applies between each
|
||||
chunk of the incoming request.
|
||||
|
||||
See also : "timeout client".
|
||||
|
||||
|
||||
2.3) Using ACLs
|
||||
---------------
|
||||
|
||||
|
@ -241,6 +241,7 @@ struct http_txn {
|
||||
char *srv_cookie; /* cookie presented by the server, in capture mode */
|
||||
int status; /* HTTP status from the server, negative if from proxy */
|
||||
unsigned int flags; /* transaction flags */
|
||||
struct timeval exp; /* expiration date for the transaction (generally a request) */
|
||||
};
|
||||
|
||||
/* This structure is used by http_find_header() to return values of headers.
|
||||
|
@ -176,7 +176,8 @@ struct proxy {
|
||||
struct timeval queue; /* queue timeout, defaults to connect if unspecified */
|
||||
struct timeval connect; /* connect timeout (in milliseconds) */
|
||||
struct timeval server; /* server I/O timeout (in milliseconds) */
|
||||
struct timeval appsession;
|
||||
struct timeval appsession; /* appsession cookie expiration */
|
||||
struct timeval httpreq; /* maximum time for complete HTTP request */
|
||||
} timeout;
|
||||
char *id; /* proxy id */
|
||||
struct list pendconns; /* pending connections with no server assigned yet */
|
||||
|
@ -521,6 +521,7 @@ static void init_default_instance()
|
||||
tv_eternity(&defproxy.timeout.appsession);
|
||||
tv_eternity(&defproxy.timeout.queue);
|
||||
tv_eternity(&defproxy.timeout.tarpit);
|
||||
tv_eternity(&defproxy.timeout.httpreq);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -603,6 +604,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
|
||||
tv_eternity(&curproxy->timeout.appsession);
|
||||
tv_eternity(&curproxy->timeout.queue);
|
||||
tv_eternity(&curproxy->timeout.tarpit);
|
||||
tv_eternity(&curproxy->timeout.httpreq);
|
||||
|
||||
curproxy->last_change = now.tv_sec;
|
||||
curproxy->id = strdup(args[1]);
|
||||
@ -663,6 +665,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
|
||||
if (curproxy->cap & PR_CAP_FE) {
|
||||
curproxy->timeout.client = defproxy.timeout.client;
|
||||
curproxy->timeout.tarpit = defproxy.timeout.tarpit;
|
||||
curproxy->timeout.httpreq = defproxy.timeout.httpreq;
|
||||
curproxy->uri_auth = defproxy.uri_auth;
|
||||
curproxy->mon_net = defproxy.mon_net;
|
||||
curproxy->mon_mask = defproxy.mon_mask;
|
||||
|
@ -390,6 +390,7 @@ int event_accept(int fd) {
|
||||
tv_eternity(&s->req->cex);
|
||||
tv_eternity(&s->rep->rex);
|
||||
tv_eternity(&s->rep->wex);
|
||||
tv_eternity(&s->txn.exp);
|
||||
tv_eternity(&t->expire);
|
||||
|
||||
if (tv_isset(&s->fe->timeout.client)) {
|
||||
@ -403,6 +404,11 @@ int event_accept(int fd) {
|
||||
}
|
||||
}
|
||||
|
||||
if (s->cli_state == CL_STHEADERS && tv_isset(&s->fe->timeout.httpreq)) {
|
||||
tv_add(&s->txn.exp, &now, &s->fe->timeout.httpreq);
|
||||
tv_bound(&t->expire, &s->txn.exp);
|
||||
}
|
||||
|
||||
task_queue(t);
|
||||
|
||||
if (p->mode != PR_MODE_HEALTH)
|
||||
|
@ -620,11 +620,12 @@ void process_session(struct task *t, struct timeval *next)
|
||||
s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
||||
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
||||
|
||||
t->expire = s->req->rex;
|
||||
tv_min(&t->expire, &s->req->rex, &s->req->wex);
|
||||
tv_bound(&t->expire, &s->req->cex);
|
||||
tv_bound(&t->expire, &s->rep->rex);
|
||||
tv_bound(&t->expire, &s->rep->wex);
|
||||
if (s->cli_state == CL_STHEADERS)
|
||||
tv_bound(&t->expire, &s->txn.exp);
|
||||
|
||||
/* restore t to its place in the task list */
|
||||
task_queue(t);
|
||||
@ -1585,7 +1586,8 @@ int process_cli(struct session *t)
|
||||
}
|
||||
|
||||
/* 3: has the read timeout expired ? */
|
||||
else if (unlikely(tv_isle(&req->rex, &now))) {
|
||||
else if (unlikely(tv_isle(&req->rex, &now) ||
|
||||
tv_isle(&txn->exp, &now))) {
|
||||
/* read timeout : give up with an error message. */
|
||||
txn->status = 408;
|
||||
client_retnclose(t, error_message(t, HTTP_ERR_408));
|
||||
|
@ -104,6 +104,10 @@ int proxy_parse_timeout(const char **args, struct proxy *proxy,
|
||||
tv = &proxy->timeout.tarpit;
|
||||
td = &defpx->timeout.tarpit;
|
||||
cap = PR_CAP_FE;
|
||||
} else if (!strcmp(args[0], "http-request")) {
|
||||
tv = &proxy->timeout.httpreq;
|
||||
td = &defpx->timeout.httpreq;
|
||||
cap = PR_CAP_FE;
|
||||
} else if (!strcmp(args[0], "server") || !strcmp(args[0], "srvtimeout")) {
|
||||
name = "server";
|
||||
tv = &proxy->timeout.server;
|
||||
@ -123,7 +127,9 @@ int proxy_parse_timeout(const char **args, struct proxy *proxy,
|
||||
td = &defpx->timeout.queue;
|
||||
cap = PR_CAP_BE;
|
||||
} else {
|
||||
snprintf(err, errlen, "timeout '%s': must be 'client', 'server', 'connect', 'appsession', 'queue', or 'tarpit'",
|
||||
snprintf(err, errlen,
|
||||
"timeout '%s': must be 'client', 'server', 'connect', "
|
||||
"'appsession', 'queue', 'http-request' or 'tarpit'",
|
||||
args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ listen sample1
|
||||
retries 1
|
||||
redispatch
|
||||
timeout client 15m
|
||||
timeout http-request 6s
|
||||
timeout tarpit 20s
|
||||
timeout queue 60s
|
||||
timeout connect 5s
|
||||
|
Loading…
x
Reference in New Issue
Block a user