Bug #79501 [ReO]: TLS connections freezing on 7.4 (all versions after 7.3.17)
| From: | imnieves at gmail dot com | 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