1#lang scribble/doc 2@(require "web-server.rkt") 3 4@title[#:tag "safety-limits"]{Safety Limits} 5@defmodule[web-server/safety-limits] 6 7@(require (for-label web-server/private/dispatch-server-unit 8 web-server/private/dispatch-server-sig 9 web-server/private/util 10 web-server/private/connection-manager 11 web-server/web-server 12 web-server/web-server-unit 13 web-server/web-config-sig 14 web-server/safety-limits 15 web-server/lang/stuff-url 16 web-server/http/request-structs 17 net/tcp-sig 18 racket/async-channel 19 racket/tcp 20 web-server/web-server-sig)) 21 22@deftogether[ 23 (@defproc[(safety-limits? [v any/c]) boolean?] 24 @defproc[(make-safety-limits 25 [#:max-waiting max-waiting exact-nonnegative-integer? 511] 26 [#:request-read-timeout request-read-timeout timeout/c 60] 27 [#:max-request-line-length max-request-line-length nonnegative-length/c 28 (code:line (* 8 1024) (code:comment #,(elem "8 KiB")))] 29 [#:max-request-headers max-request-headers nonnegative-length/c 100] 30 [#:max-request-header-length max-request-header-length nonnegative-length/c 31 (code:line (* 8 1024) (code:comment #,(elem "8 KiB")))] 32 [#:max-request-body-length max-request-body-length nonnegative-length/c 33 (code:line (* 1 1024 1024) (code:comment #,(elem "1 MiB")))] 34 [#:max-form-data-parts max-form-data-parts nonnegative-length/c 35 (+ max-form-data-fields max-form-data-files)] 36 [#:max-form-data-header-length max-form-data-header-length nonnegative-length/c 37 (code:line (* 8 1024) (code:comment #,(elem "8 KiB")))] 38 [#:max-form-data-files max-form-data-files nonnegative-length/c 100] 39 [#:max-form-data-file-length max-form-data-file-length nonnegative-length/c 40 (code:line (* 10 1024 1024) (code:comment #,(elem "10 MiB")))] 41 [#:form-data-file-memory-threshold form-data-file-memory-threshold nonnegative-length/c 42 (code:line (* 1 1024 1024) (code:comment #,(elem "1 MiB")))] 43 [#:max-form-data-fields max-form-data-fields nonnegative-length/c 100] 44 [#:max-form-data-field-length max-form-data-field-length nonnegative-length/c 45 (code:line (* 8 1024) (code:comment #,(elem "8 KiB")))] 46 [#:response-timeout response-timeout timeout/c 60] 47 [#:response-send-timeout response-send-timeout timeout/c 60]) 48 safety-limits?] 49 @defthing[nonnegative-length/c flat-contract? 50 #:value (or/c exact-nonnegative-integer? +inf.0)] 51 @defthing[timeout/c flat-contract? 52 #:value (>=/c 0)])]{ 53 The web server uses opaque @deftech{safety limits} values, recognized 54 by the predicate @racket[safety-limits?], to encapsulate 55 policies for protection against misbehaving or malicious clients and servlets. 56 Construct @tech{safety limits} values using @racket[make-safety-limits], 57 which supplies reasonably safe default policies that should work for most applications. 58 See the @elemref["safety-limits-porting"]{compatability note} and 59 @racket[make-unlimited-safety-limits] for further details. 60 61 The arguments to @racket[make-safety-limits] are used as follows: 62 @itemlist[ 63 @item{The @racket[max-waiting] argument is passed to @racket[tcp-listen] 64 to specify the maximum number of client connections that can be waiting for acceptance. 65 When @racket[max-waiting] clients are waiting for acceptance, no new client connections can be made. 66 } 67 @item{The @racket[request-read-timeout] limits how long, in seconds, 68 the standard @sigelem[dispatch-server-config*^ read-request] implementation 69 (e.g. from @racket[serve] or @racket[web-server@]) 70 will wait for request data to come in from the client 71 before it closes the connection. 72 If you need to support large file uploads over slow connections, 73 you may need to adjust this value. 74 } 75 @item{The @racket[max-request-line-length] limits the length (in bytes) of the 76 the first line of an HTTP request (the ``request line''), 77 which specifies the request method, path, and protocol version. 78 Requests with a first line longer than @racket[max-request-line-length] 79 are rejected by the standard @sigelem[dispatch-server-config*^ read-request] 80 implementation (e.g. from @racket[serve] or @racket[web-server@]). 81 Increase this if you have very long URLs, but see also @racket[is-url-too-big?]. 82 } 83 @item{The @racket[max-request-headers] and @racket[max-request-header-length] 84 arguments limit the number of headers allowed per HTTP request 85 and the length, in bytes, of an individual request header, respectively. 86 Requests that exceed these limits are rejected by the standard 87 @sigelem[dispatch-server-config*^ read-request] 88 implementation (e.g. from @racket[serve] or @racket[web-server@]). 89 } 90 @item{The @racket[max-request-body-length] limits the size, in bytes, 91 of HTTP request bodies---but it does not apply to multipart (file upload) 92 requests: see @racket[max-form-data-files] and related limits, below. 93 Requests with bodies longer than @racket[max-request-body-length] 94 are rejected by the standard @sigelem[dispatch-server-config*^ read-request] 95 implementation (e.g. from @racket[serve] or @racket[web-server@]). 96 } 97 @item{The @racket[max-form-data-files], @racket[max-form-data-fields], 98 @racket[max-form-data-file-length], @racket[max-form-data-field-length], 99 @racket[max-form-data-parts], @racket[form-data-file-memory-threshold], 100 and @racket[max-form-data-header-length] arguments control the handling of 101 @tt{multipart/form-data} (file upload) requests by the standard 102 @sigelem[dispatch-server-config*^ read-request] 103 implementation (e.g. from @racket[serve] or @racket[web-server@]). 104 105 The number of files and non-file ``fields'' per request are limited by 106 @racket[max-form-data-files] and @racket[max-form-data-fields], respectively, 107 and @racket[max-form-data-file-length] and @racket[max-form-data-field-length] 108 limit the length, in bytes, of an individual file or non-file field. 109 Additionally, the total number of ``parts,'' which includes both files and fields, 110 must not exceed @racket[max-form-data-parts]. 111 Requests that exceed these limits are rejected. 112 113 Files longer than @racket[request-file-memory-threshold], in bytes, 114 are automatically offloaded to disk as temporary files 115 to avoid running out of memory. 116 117 The @racket[max-form-data-header-length] argument limits the length of a header 118 for an individual part (file or field). 119 Since such headers are already tightly constrained by 120 @hyperlink["https://tools.ietf.org/html/rfc7578#section-4.8"]{RFC 7578 §4.8.}, 121 it should be especially rare to need to increase this limit, 122 but doing so could allow for exceptionally long file or field names. 123 } 124 @item{The @racket[response-timeout] and @racket[response-send-timeout] 125 arguments limit the time for which individual request handlers 126 (as in @sigelem[dispatch-server-config*^ dispatch]) are allowed to run. 127 128 The @racket[response-timeout] specifies the maximum time, in seconds, 129 that a handler is allowed to run after the request has been read 130 before it writes its first byte of response data. 131 If no data is written within this time limit, the connection is killed. 132 133 The @racket[response-send-timeout] specifies the maximum time, in seconds, 134 that the server will wait for a chunk of response data. 135 Each time a chunk of data is sent to the client, this timeout resets. 136 If your application uses streaming responses or long polling, 137 either adjust this value or make sure that your request handler sends 138 data periodically, such as a no-op, to avoid hitting this limit. 139 }] 140 141 142 @elemtag["safety-limits-porting"]{@bold{Compatibility note:}} 143 The @tech{safety limits} type may be extended in the future to provide 144 additional protections. 145 Creating @tech{safety limits} values with @racket[make-safety-limits] 146 will allow applications to take advantage of reasonable default values 147 for any new limits that are added. 148 However, adding new limits does have the potential to break some existing 149 applications: as an alternative, the @racket[make-unlimited-safety-limits] 150 constructor uses default values that avoid imposing any limits that 151 aren't explicitly specified. (In most cases, this means a default of @racket[+inf.0].) 152 Of course, applications using @racket[make-unlimited-safety-limits] 153 may remain vulnerable to threats which the values from @racket[make-safety-limits] 154 would have protected against. 155 156 The @tech{safety limits} type was introduced in version 1.6 of the 157 @tt{web-server-lib} package. 158 Previous versions of this library only supported the @racket[max-waiting] limit 159 and (in some cases) an @racket[initial-connection-timeout] limit, 160 which was similar to @racket[request-read-timeout], but had 161 @hyperlink["https://github.com/racket/web-server/pull/77"]{some problems}. 162 These limits were specified through @racket[dispatch-server-config^], @racket[web-config^], 163 and optional arguments to functions like @racket[serve]: 164 if values weren't explicitly supplied, the default behavior was closest to using 165 @racket[(make-unlimited-safety-limits #:request-read-timeout 60)]. 166 167 However, version 1.6 adopted @racket[(make-safety-limits)] as the default, 168 as most applications would benefit from using reasonable protections. 169 When porting from earlier versions of this library, 170 if you think your application may be especially resource-intensive, 171 you may prefer to use @racket[make-unlimited-safety-limits] while determining 172 limits that work for your application. 173 174 @history[#:added "1.6"] 175} 176 177@defproc[(make-unlimited-safety-limits 178 [#:max-waiting max-waiting exact-nonnegative-integer? 511] 179 [#:request-read-timeout request-read-timeout timeout/c +inf.0] 180 [#:max-request-line-length max-request-line-length nonnegative-length/c +inf.0] 181 [#:max-request-headers max-request-headers nonnegative-length/c +inf.0] 182 [#:max-request-header-length max-request-header-length nonnegative-length/c +inf.0] 183 [#:max-request-body-length max-request-body-length nonnegative-length/c +inf.0] 184 [#:max-request-files max-request-files nonnegative-length/c +inf.0] 185 [#:max-request-file-length max-request-file-length nonnegative-length/c +inf.0] 186 [#:request-file-memory-threshold request-file-memory-threshold nonnegative-length/c +inf.0] 187 [#:max-form-data-parts max-form-data-parts nonnegative-length/c +inf.0] 188 [#:max-form-data-header-length max-form-data-header-length nonnegative-length/c +inf.0] 189 [#:max-form-data-files max-form-data-files nonnegative-length/c +inf.0] 190 [#:max-form-data-file-length max-form-data-file-length nonnegative-length/c +inf.0] 191 [#:form-data-file-memory-threshold form-data-file-memory-threshold nonnegative-length/c +inf.0] 192 [#:max-form-data-fields max-form-data-fields nonnegative-length/c +inf.0] 193 [#:max-form-data-field-length max-form-data-field-length nonnegative-length/c +inf.0] 194 [#:response-timeout response-timeout timeout/c +inf.0] 195 [#:response-send-timeout response-send-timeout timeout/c +inf.0]) 196 safety-limits?]{ 197 Like @racket[make-safety-limits], but with default values that avoid 198 imposing any limits that aren't explicitly specified, 199 rather than the safer defaults of @racket[make-safety-limits]. 200 Think carefully before using @racket[make-unlimited-safety-limits], 201 as it may leave your application vulnerable to denial of service attacks 202 or other threats that the default values from @racket[make-safety-limits] would mitigate. 203 See the @elemref["safety-limits-porting"]{compatability note} for more details. 204 205 Note that the default value for @racket[max-waiting] is @racket[511], 206 @italic{not} @racket[+inf.0], due to the contract of @racket[tcp-listen]. 207 208 @history[#:added "1.6"] 209} 210