From 5f666a2385a9f07d83da6b36fe0e8eddad85682f Mon Sep 17 00:00:00 2001 From: Stefan Fritsch Date: Tue, 8 Nov 2011 20:41:47 +0000 Subject: [PATCH] mod_reqtimeout: Change the default to set some reasonable timeout values if loaded git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1199447 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 3 + docs/conf/extra/httpd-default.conf.in | 15 ++++ docs/manual/mod/mod_reqtimeout.xml | 17 ++++- docs/manual/upgrading.xml | 3 + modules/filters/mod_reqtimeout.c | 101 +++++++++++++++++--------- 5 files changed, 102 insertions(+), 37 deletions(-) diff --git a/CHANGES b/CHANGES index 6989966d88..559c2021d0 100644 --- a/CHANGES +++ b/CHANGES @@ -16,6 +16,9 @@ Changes with Apache 2.3.15 core: Fix integer overflow in ap_pregsub. This can be triggered e.g. with mod_setenvif via a malicious .htaccess. [Stefan Fritsch] + *) mod_reqtimeout: Change the default to set some reasonable timeout + values. [Stefan Fritsch] + *) core, mod_dav_fs: Change default ETag to be "size mtime", i.e. remove the inode. PR 49623. [Stefan Fritsch] diff --git a/docs/conf/extra/httpd-default.conf.in b/docs/conf/extra/httpd-default.conf.in index 15352b969f..f1e7bc82a7 100644 --- a/docs/conf/extra/httpd-default.conf.in +++ b/docs/conf/extra/httpd-default.conf.in @@ -73,3 +73,18 @@ ServerSignature Off # nameserver. # HostnameLookups Off + +# +# Set a timeout for how long the client may take to send the request header +# and body. +# The default for the headers is header=20-40,MinRate=500, which means wait +# for the first byte of headers for 20 seconds. If some data arrives, +# increase the timeout corresponding to a data rate of 500 bytes/s, but not +# above 40 seconds. +# The default for the request body is body=20,MinRate=500, which is the same +# but has no upper limit for the timeout. +# To disable, set to header=0 body=0 +# + + RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500 + diff --git a/docs/manual/mod/mod_reqtimeout.xml b/docs/manual/mod/mod_reqtimeout.xml index d5f16a96b4..3707843081 100644 --- a/docs/manual/mod/mod_reqtimeout.xml +++ b/docs/manual/mod/mod_reqtimeout.xml @@ -28,7 +28,7 @@ Extension mod_reqtimeout.c reqtimeout_module -Available in Apache 2.2.15 and later +Available in Apache HTTPD 2.2.15 and later
Examples @@ -83,12 +83,14 @@ Set timeout values for receiving request headers and body from client. RequestReadTimeout -[header=timeout[[-maxtimeout],MinRate=rate] -[body=timeout[[-maxtimeout],MinRate=rate] +[header=timeout[-maxtimeout][,MinRate=rate] +[body=timeout[-maxtimeout][,MinRate=rate] -Unset; no limit +header=20-40,MinRate=500 body=20,MinRate=500 server configvirtual host +Available in version 2.2.15 and later; defaulted to disabled in +version 2.3.14 and earlier.

This directive can set various timeouts for receiving the request headers @@ -126,6 +128,13 @@ body, respectively. A value of 0 means no limit.

+
  • Disable module for a vhost::
    + + header=0 body=0 + +

    This disables mod_reqtimeout completely.

    +
  • +
  • Timeout value that is increased when data is received:
    diff --git a/docs/manual/upgrading.xml b/docs/manual/upgrading.xml index e7fff87970..5c78026fd0 100644 --- a/docs/manual/upgrading.xml +++ b/docs/manual/upgrading.xml @@ -269,6 +269,9 @@ limited to 1MB.
  • +
  • mod_reqtimeout: If the module is loaded, it + will now set some default timeouts.
  • +
    diff --git a/modules/filters/mod_reqtimeout.c b/modules/filters/mod_reqtimeout.c index de19536b2c..800bb6b4a9 100644 --- a/modules/filters/mod_reqtimeout.c +++ b/modules/filters/mod_reqtimeout.c @@ -28,6 +28,14 @@ module AP_MODULE_DECLARE_DATA reqtimeout_module; +#define UNSET -1 +#define MRT_DEFAULT_HEADER_TIMEOUT 20 +#define MRT_DEFAULT_HEADER_MAX_TIMEOUT 40 +#define MRT_DEFAULT_HEADER_MIN_RATE 500 +#define MRT_DEFAULT_BODY_TIMEOUT 20 +#define MRT_DEFAULT_BODY_MAX_TIMEOUT 0 +#define MRT_DEFAULT_BODY_MIN_RATE 500 + typedef struct { int header_timeout; /* timeout for reading the req hdrs in secs */ @@ -56,6 +64,8 @@ typedef struct } reqtimeout_con_cfg; static const char *const reqtimeout_filter_name = "reqtimeout"; +static int default_header_rate_factor; +static int default_body_rate_factor; static void extend_timeout(reqtimeout_con_cfg *ccfg, apr_bucket_brigade *bb) { @@ -161,7 +171,7 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f, apr_time_t time_left; apr_time_t now; apr_status_t rv; - apr_interval_time_t saved_sock_timeout = -1; + apr_interval_time_t saved_sock_timeout = UNSET; reqtimeout_con_cfg *ccfg = f->ctx; if (ccfg->in_keep_alive) { @@ -325,17 +335,25 @@ static int reqtimeout_init(conn_rec *c) cfg = ap_get_module_config(c->base_server->module_config, &reqtimeout_module); AP_DEBUG_ASSERT(cfg != NULL); - if (cfg->header_timeout <= 0 && cfg->body_timeout <= 0) { - /* not configured for this vhost */ + if (cfg->header_timeout == 0 && cfg->body_timeout == 0) { + /* disabled for this vhost */ return DECLINED; } ccfg = apr_pcalloc(c->pool, sizeof(reqtimeout_con_cfg)); - ccfg->new_timeout = cfg->header_timeout; - ccfg->new_max_timeout = cfg->header_max_timeout; ccfg->type = "header"; - ccfg->min_rate = cfg->header_min_rate; - ccfg->rate_factor = cfg->header_rate_factor; + if (cfg->header_timeout != UNSET) { + ccfg->new_timeout = cfg->header_timeout; + ccfg->new_max_timeout = cfg->header_max_timeout; + ccfg->min_rate = cfg->header_min_rate; + ccfg->rate_factor = cfg->header_rate_factor; + } + else { + ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT; + ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT; + ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE; + ccfg->rate_factor = default_header_rate_factor; + } ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg); ap_add_input_filter("reqtimeout", ccfg, NULL, c); @@ -349,25 +367,29 @@ static int reqtimeout_after_headers(request_rec *r) reqtimeout_con_cfg *ccfg = ap_get_module_config(r->connection->conn_config, &reqtimeout_module); - if (ccfg == NULL) { - /* not configured for this connection */ + if (ccfg == NULL || r->method_number == M_CONNECT) { + /* either disabled for this connection or a CONNECT request */ return OK; } - cfg = ap_get_module_config(r->connection->base_server->module_config, &reqtimeout_module); AP_DEBUG_ASSERT(cfg != NULL); ccfg->timeout_at = 0; ccfg->max_timeout_at = 0; - if (r->method_number != M_CONNECT) { - ccfg->new_timeout = cfg->body_timeout; + ccfg->type = "body"; + if (cfg->body_timeout != UNSET) { + ccfg->new_timeout = cfg->body_timeout; ccfg->new_max_timeout = cfg->body_max_timeout; - ccfg->min_rate = cfg->body_min_rate; - ccfg->rate_factor = cfg->body_rate_factor; - ccfg->type = "body"; + ccfg->min_rate = cfg->body_min_rate; + ccfg->rate_factor = cfg->body_rate_factor; + } + else { + ccfg->new_timeout = MRT_DEFAULT_BODY_TIMEOUT; + ccfg->new_max_timeout = MRT_DEFAULT_BODY_MAX_TIMEOUT; + ccfg->min_rate = MRT_DEFAULT_BODY_MIN_RATE; + ccfg->rate_factor = default_body_rate_factor; } - return OK; } @@ -389,12 +411,19 @@ static int reqtimeout_after_body(request_rec *r) ccfg->timeout_at = 0; ccfg->max_timeout_at = 0; ccfg->in_keep_alive = 1; - ccfg->new_timeout = cfg->header_timeout; - ccfg->new_max_timeout = cfg->header_max_timeout; - ccfg->min_rate = cfg->header_min_rate; - ccfg->rate_factor = cfg->header_rate_factor; - ccfg->type = "header"; + if (ccfg->new_timeout != UNSET) { + ccfg->new_timeout = cfg->header_timeout; + ccfg->new_max_timeout = cfg->header_max_timeout; + ccfg->min_rate = cfg->header_min_rate; + ccfg->rate_factor = cfg->header_rate_factor; + } + else { + ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT; + ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT; + ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE; + ccfg->rate_factor = default_header_rate_factor; + } return OK; } @@ -403,17 +432,17 @@ static void *reqtimeout_create_srv_config(apr_pool_t *p, server_rec *s) { reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg)); - cfg->header_timeout = -1; - cfg->header_max_timeout = -1; - cfg->header_min_rate = -1; - cfg->body_timeout = -1; - cfg->body_max_timeout = -1; - cfg->body_min_rate = -1; + cfg->header_timeout = UNSET; + cfg->header_max_timeout = UNSET; + cfg->header_min_rate = UNSET; + cfg->body_timeout = UNSET; + cfg->body_max_timeout = UNSET; + cfg->body_min_rate = UNSET; return cfg; } -#define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == -1) ? b->val : a->val; +#define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == UNSET) ? b->val : a->val; static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_) { reqtimeout_srv_cfg *base = base_; @@ -427,11 +456,10 @@ static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_) MERGE_INT(cfg, base, add, body_max_timeout); MERGE_INT(cfg, base, add, body_min_rate); - cfg->header_rate_factor = (cfg->header_min_rate == -1) ? base->header_rate_factor : - add->header_rate_factor; - cfg->body_rate_factor = (cfg->body_min_rate == -1) ? base->body_rate_factor : - add->body_rate_factor; - + cfg->header_rate_factor = (cfg->header_min_rate == UNSET) ? + base->header_rate_factor : add->header_rate_factor; + cfg->body_rate_factor = (cfg->body_min_rate == UNSET) ? + base->body_rate_factor : add->body_rate_factor; return cfg; } @@ -574,6 +602,13 @@ static void reqtimeout_hooks(apr_pool_t *pool) APR_HOOK_MIDDLE); ap_hook_log_transaction(reqtimeout_after_body, NULL, NULL, APR_HOOK_MIDDLE); + +#if MRT_DEFAULT_HEADER_MIN_RATE > 0 + default_header_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_HEADER_MIN_RATE; +#endif +#if MRT_DEFAULT_BODY_MIN_RATE > 0 + default_body_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_BODY_MIN_RATE; +#endif } static const command_rec reqtimeout_cmds[] = { -- 2.40.0