]> granicus.if.org Git - apache/commitdiff
mod_reqtimeout: Change the default to set some reasonable timeout values if loaded
authorStefan Fritsch <sf@apache.org>
Tue, 8 Nov 2011 20:41:47 +0000 (20:41 +0000)
committerStefan Fritsch <sf@apache.org>
Tue, 8 Nov 2011 20:41:47 +0000 (20:41 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1199447 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/conf/extra/httpd-default.conf.in
docs/manual/mod/mod_reqtimeout.xml
docs/manual/upgrading.xml
modules/filters/mod_reqtimeout.c

diff --git a/CHANGES b/CHANGES
index 6989966d88aee8d67234e3ca02698f9aa22b046f..559c2021d0418e66f399cdc3b323b6f9a7b64aef 100644 (file)
--- 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]
 
index 15352b969f18f0a02de156b20f3499ea500b6030..f1e7bc82a7715ba7d62655cfaccfdcf0a361584d 100644 (file)
@@ -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
+#
+<IfModule reqtimeout_module>
+  RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
+</IfModule>
index d5f16a96b4dac4701afd9eaed1ebbebeb4c2c227..3707843081ebba4f48c8dfcbc91f38eff7edf299 100644 (file)
@@ -28,7 +28,7 @@
 <status>Extension</status>
 <sourcefile>mod_reqtimeout.c</sourcefile>
 <identifier>reqtimeout_module</identifier>
-<compatibility>Available in Apache 2.2.15 and later</compatibility>
+<compatibility>Available in Apache HTTPD 2.2.15 and later</compatibility>
 
 <section id="examples"><title>Examples</title>
 
 <description>Set timeout values for receiving request headers and body from client.
 </description>
 <syntax>RequestReadTimeout
-[header=<var>timeout</var>[[-<var>maxtimeout</var>],MinRate=<var>rate</var>]
-[body=<var>timeout</var>[[-<var>maxtimeout</var>],MinRate=<var>rate</var>]
+[header=<var>timeout</var>[-<var>maxtimeout</var>][,MinRate=<var>rate</var>]
+[body=<var>timeout</var>[-<var>maxtimeout</var>][,MinRate=<var>rate</var>]
 </syntax>
-<default>Unset; no limit</default>
+<default>header=20-40,MinRate=500 body=20,MinRate=500</default>
 <contextlist><context>server config</context><context>virtual host</context>
 </contextlist>
+<compatibility>Available in version 2.2.15 and later; defaulted to disabled in
+version 2.3.14 and earlier.</compatibility>
 
 <usage>
     <p>This directive can set various timeouts for receiving the request headers
     body, respectively. A value of 0 means no limit.</p>
     </li>
 
+    <li><strong>Disable module for a vhost:</strong>:<br />
+
+    <example>header=0 body=0</example>
+
+    <p>This disables <module>mod_reqtimeout</module> completely.</p>
+    </li>
+
     <li><strong>Timeout value that is increased when data is
     received</strong>:<br />
     <example>
index e7fff87970ee3ff43870c2d3bdafb74cc1a0a27d..5c78026fd05ed3e145c1c998fbb32fb175c30af3 100644 (file)
         limited to 1MB.
         </li>
 
+        <li><module>mod_reqtimeout</module>: If the module is loaded, it
+        will now set some default timeouts.</li>
+
       </ul>
     </section>
   </section>
index de19536b2c6d85e4379838853232a6370f17907a..800bb6b4a976d9be675eb450fe3c6d789ecfad6a 100644 (file)
 
 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[] = {