From: Willy Tarreau Date: Mon, 24 Oct 2011 17:14:41 +0000 (+0200) Subject: MEDIUM: tune.http.maxhdr makes it possible to configure the maximum number of HTTP... X-Git-Tag: v1.5-dev8~83 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac1932d;p=thirdparty%2Fhaproxy.git MEDIUM: tune.http.maxhdr makes it possible to configure the maximum number of HTTP headers For a long time, the max number of headers was taken as a part of the buffer size. Since the header size can be configured at runtime, it does not make much sense anymore. Nothing was making it necessary to have a static value, so let's turn this into a tunable with a default value of 101 which equals what was previously used. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 5cce3b46b8..afe1bfc655 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -458,6 +458,7 @@ The following keywords are supported in the "global" section : - spread-checks - tune.bufsize - tune.chksize + - tune.http.maxhdr - tune.maxaccept - tune.maxpollevents - tune.maxrewrite @@ -725,6 +726,17 @@ tune.chksize build time. It is not recommended to change this value, but to use better checks whenever possible. +tune.http.maxhdr + Sets the maximum number of headers in a request. When a request comes with a + number of headers greater than this value (including the first line), it is + rejected with a "400 Bad Request" status code. Similarly, too large responses + are blocked with "502 Bad Gateway". The default value is 101, which is enough + for all usages, considering that the widely deployed Apache server uses the + same limit. It can be useful to push this limit further to temporarily allow + a buggy application to work by the time it gets fixed. Keep in mind that each + new header consumes 32bits of memory for each session, so don't push this + limit too high. + tune.maxaccept Sets the maximum number of consecutive accepts that a process may perform on a single wake up. High values give higher priority to high connection rates, diff --git a/include/common/defaults.h b/include/common/defaults.h index 0a4f42068f..8647131378 100644 --- a/include/common/defaults.h +++ b/include/common/defaults.h @@ -58,9 +58,9 @@ #define MAX_MATCH 10 // max # of headers in one HTTP request or response -// By default, about 100 headers per 8 kB. +// By default, about 100 headers (+1 for the first line) #ifndef MAX_HTTP_HDR -#define MAX_HTTP_HDR ((BUFSIZE+79)/80) +#define MAX_HTTP_HDR 101 #endif // max # of headers in history when looking for header #-X diff --git a/include/types/global.h b/include/types/global.h index 078a1d55cb..56110e8d22 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -97,6 +97,7 @@ struct global { int server_rcvbuf; /* set server rcvbuf to this value if not null */ int chksize; /* check buffer size in bytes, defaults to BUFSIZE */ int pipesize; /* pipe size in bytes, system defaults if zero */ + int max_http_hdr; /* max number of HTTP headers, use MAX_HTTP_HDR if zero */ } tune; struct { char *prefix; /* path prefix of unix bind socket */ diff --git a/include/types/proto_http.h b/include/types/proto_http.h index d9bf830964..f1b3eef524 100644 --- a/include/types/proto_http.h +++ b/include/types/proto_http.h @@ -322,7 +322,7 @@ struct http_req_rule { */ struct http_txn { struct http_msg req; /* HTTP request message */ - struct hdr_idx hdr_idx; /* array of header indexes (max: MAX_HTTP_HDR) */ + struct hdr_idx hdr_idx; /* array of header indexes (max: global.tune.max_http_hdr) */ unsigned int flags; /* transaction flags */ http_meth_t meth; /* HTTP method */ diff --git a/src/cfgparse.c b/src/cfgparse.c index dac6bcab5e..5ddfbe26fe 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -596,6 +596,14 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm) } global.tune.pipesize = atol(args[1]); } + else if (!strcmp(args[0], "tune.http.maxhdr")) { + if (*(args[1]) == 0) { + Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + global.tune.max_http_hdr = atol(args[1]); + } else if (!strcmp(args[0], "uid")) { if (global.uid != 0) { Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum); @@ -6595,8 +6603,11 @@ out_uri_auth_compat: } } + if (!global.tune.max_http_hdr) + global.tune.max_http_hdr = MAX_HTTP_HDR; + pool2_hdr_idx = create_pool("hdr_idx", - MAX_HTTP_HDR * sizeof(struct hdr_idx_elem), + global.tune.max_http_hdr * sizeof(struct hdr_idx_elem), MEM_F_SHARED); if (cfgerr > 0) diff --git a/src/frontend.c b/src/frontend.c index 195a42414d..19980c0f41 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -134,7 +134,7 @@ int frontend_accept(struct session *s) * that we may make use of them. This of course includes * (mode == PR_MODE_HTTP). */ - s->txn.hdr_idx.size = MAX_HTTP_HDR; + s->txn.hdr_idx.size = global.tune.max_http_hdr; if (unlikely((s->txn.hdr_idx.v = pool_alloc2(pool2_hdr_idx)) == NULL)) goto out_free_rspcap; /* no memory */ diff --git a/src/proxy.c b/src/proxy.c index d274dfe5fb..caec45d485 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -819,7 +819,7 @@ int session_set_backend(struct session *s, struct proxy *be) /* and now initialize the HTTP transaction state */ http_init_txn(s); - s->txn.hdr_idx.size = MAX_HTTP_HDR; + s->txn.hdr_idx.size = global.tune.max_http_hdr; hdr_idx_init(&s->txn.hdr_idx); }