Bug #79501 [ReO]: TLS connections freezing on 7.4 (all versions after 7.3.17)

From: Date: Wed, 02 Feb 2022 22:28:54 +0000
Subject: Bug #79501 [ReO]: TLS connections freezing on 7.4 (all versions after 7.3.17)
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-239425@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=79501&edit=1 ID: 79501 User updated by: imnieves at gmail dot com Reported by: imnieves at gmail dot com Summary: TLS connections freezing on 7.4 (all versions after 7.3.17) Status: Re-Opened Type: Bug Package: OpenSSL related Operating System: Linux PHP Version: 7.4.5 Block user comment: N Private report: N New Comment: I will break this message into two parts, hopefully that will help this message to not be detected as SPAM. I was able to determine the exact line that is blocking in PHP series 7.4 (7.4..27 precisely) when TLS 1.3 is being used. The offending line is: https://github.com/php/php-src/blob/96f753a2b56b7c4927f1a64253ca60bb481ee2c3/ext/openssl/xp_ssl.c#L2466 int n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf)); For reference, the PHP method that calls this SSL_peek is itself called at: https://github.com/php/php-src/blob/96f753a2b56b7c4927f1a64253ca60bb481ee2c3/main/streams/streams.c#L790 if (!stream->eof && PHP_STREAM_OPTION_RETURN_ERR == php_stream_set_option(stream, PHP_STREAM_OPTION_CHECK_LIVENESS, 0, NULL)) { stream->eof = 1; } After reading about so-called SSL non-application data records: https://github.com/openssl/openssl/blob/6e94b5aecd619afd25e3dc25902952b1b3194edf/CHANGES#L237 https://wiki.openssl.org/index.php/TLS1.3#Non-application_data_records openssl/openssl#7327 I believe the blocking is occurring because PHP 7.4 is assuming (in xp_ssl.c @ L2466, the first code snippet above) that if there is a record that can be read, then the record must be a data record and therefore the SSL_peek will not block. This assumption is false in both TLS 1.2 and TLS 1.3, however the impact of this assumption is felt rarely (if at all) in TLS 1.2 but it arises frequently in TLS 1.3, in fact it arises instantly in TLS 1.3. In TLS 1.2, this line: https://github.com/php/php-src/blob/96f753a2b56b7c4927f1a64253ca60bb481ee2c3/ext/openssl/xp_ssl.c#L2464 } else if (php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) { evaluates to false. But in TLS 1.3 it evaluates to true, which enables SSL_peek to be called, and block. Previous Comments: ------------------------------------------------------------------------ [2020-08-08 17:58:30] imnieves at gmail dot com According to comment from a maintainer of PhpRedis[1], they feel that the issue is not coming from PhpRedis itself: | I'm going to close this issue because it is actually not a bug in phpredis. [1] https://github.com/phpredis/phpredis/issues/1726#issuecomment-652563196 ------------------------------------------------------------------------ [2020-05-08 11:41:24] cmb@php.net According to a comment on the PhpRedis issue[1] this might be an issue with our tlsv1.3 stream wrapper implementation: | […] because right now it looks like something may be wrong in | PhpRedis even if it just wraps php streams. [1] <https://github.com/phpredis/phpredis/issues/1726#issuecomment-625319182> ------------------------------------------------------------------------ [2020-05-06 20:54:16] imnieves at gmail dot com In a separate method of testing, I constrained TLS versions of phpredis (instead of constraining TLS versions of nginx) In this way I have verified on php 7.4.5-fpm that TLS 1.2 results in consistent working connections. TLS 1.3 results in some connections that work and most other connections that fail. I can also say the cipher suite being used in all my TLS 1.3 connections (consistent and freezing): TLS_AES_256_GCM_SHA384 ------------------------------------------------------------------------ [2020-05-06 20:51:54] imnieves at gmail dot com I have verified that TLS 1.2 connections work consistently, while TLS 1.3 connections freeze (fail to establish) on PHP 7.4.5-fpm. On the other side of the testing, both TLS 1.2 and TLS 1.3 connections work consistently on PHP 7.3.17-fpm. To perform this test I put nginx in front of my Redis, disabled TLS on Redis entirely, and enabled TLS on nginx. I varied the TLS settings on nginx as follows: TLS 1.2 only, then TLS 1.3 only, then both TLS 1.2 and TLS 1.3. Interesting to note, when nginx has: only TLS 1.2, the connections always work only TLS 1.3, the connections always freeze both TLS 1.2 and TLS 1.3, the connections work for the first 5 attempts, and then one freezes. If I attempt another connection then the next 4 or 5 connections succeed and then another one freezes. And this cycle repeats. ------------------------------------------------------------------------ [2020-05-06 19:00:45] imnieves at gmail dot com I will investigate ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=79501 -- Edit this bug report at https://bugs.php.net/bug.php?id=79501&edit=1

« previous php.bugs (#239425) next »