Bug 61310

Summary: mod_reqtimeout does not timeout during SSL handshakes
Product: Apache httpd-2 Reporter: apache.bugs
Component: mod_reqtimeoutAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: RESOLVED FIXED    
Severity: enhancement CC: apache.bugs
Priority: P2 Keywords: FixedInTrunk
Version: 2.4.26   
Target Milestone: ---   
Hardware: PC   
OS: FreeBSD   
Attachments: Allow to configure TLS handshake timeout(s)

Description apache.bugs 2017-07-16 22:00:19 UTC
It seems that `mod_reqtimeout` timeout only starts when the SSL handshake has been fulfilled.

Here is a simple configuration to show the issue:

    # Ensure that accept filters do not interfere
    AcceptFilter http none
    AcceptFilter https none
    # Apache core timeout
    Timeout 30
    # mod_reqtimeout timeout
    RequestReadTimeout header=5 body=5

A connection made with `openssl s_client` correctly times out after 5 seconds as expected:

    user@host:~$ time openssl s_client -quiet -host www.mydomain.test -port 443
    depth=0 CN = default.invalid
    verify error:num=18:self signed certificate
    verify return:1
    depth=0 CN = default.invalid
    verify return:1
    
    real  0m5.082s
    user  0m0.006s
    sys   0m0.016s

However a connection made using `telnet` remains during 30 seconds, until Apache core global `Timeout` value expires:

    user@host:~$ time telnet www.mydomain.test 443
    Trying 192.168.0.1...
    Connected to mydomain.test.
    Escape character is '^]'.
    Connection closed by foreign host.
    
    real  0m30.028s
    user  0m0.003s
    sys   0m0.012s

The expected behavior is for this connection to be interrupted after 5 seconds too, as defined in the `RequestReadTimeout` setting.

For reference, `mod_reqtimeout` documentation[1] seems to imply that its timeout should cover the SSL handshake ("If a common configuration is used for http and https virtual hosts, the timeouts should not be set too low") which does not seem to the be case here, hence the bug report.

Moreover, `mod_reqtimeout` is cited by Wikipedia[2] as the "the official solution supported by the developers" to mitigate Slowloris class of attacks. The fact that it does not impose any timeout on the SSL handshake strongly limits its effectiveness for such use.

[1]: https://httpd.apache.org/docs/2.4/mod/mod_reqtimeout.html
[2]: https://en.wikipedia.org/wiki/Slowloris_(computer_security)#Mitigating_the_Slowloris_attack
Comment 1 dferradal 2019-02-15 18:05:10 UTC
as replied in #httpd in irc:

mod_reqtimeout deals with HTTP attacks, checks the timing for HTTP requests, including headers, body.

HTTP communication does no happen until SSL negotiation has been established correctly.

So it is normal openssl timesout with mod_reqtimeout because SSL negotiation has been stablished already.

And it is normal telnet timesout with global server config timeout instead of mod_reqtimeout, because SSL negotiation has not been made and thus we are not in http communication yet.

I'd declare this INVALID.
Comment 2 Yann Ylavic 2019-02-15 22:26:30 UTC
Right, switching to "enhancement" though, maybe we can have a new handshake=timeout[-maxtimeout][,MinRate=rate] setting which would act at the TLS handhake level. Will look into this, unless one beats me to it :)
Comment 3 Yann Ylavic 2019-02-15 23:38:21 UTC
Created attachment 36438 [details]
Allow to configure TLS handshake timeout(s)

Something like this.
Comment 4 Yann Ylavic 2019-02-19 18:25:50 UTC
Committed to trunk (r1853906, with first preparation commit in r1853901)
Comment 5 Yann Ylavic 2019-03-27 21:54:37 UTC
Backported to 2.4.39 (r1855409).