reactphp / socket

Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP.

Home Page:https://reactphp.org/socket/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

verify_peer should default to false for React\Socket\Server using TLS context

michaelphipps opened this issue · comments

Reporting this issue as requested by @clue from this twitter in this twitter thread https://twitter.com/PhippsyTech/status/1414239527112085512

TLDR;
According to Christian,verify_peer should default to false for server-side sockets, and not be required in the tls context.

Here is my code:

$webSock = new React\Socket\Server('tls://0.0.0.0:'.WEBSOCKET_PORT, null, array(
    "tls" => array(
        'local_cert' => '/etc/letsencrypt/live/'.DOMAIN.'/fullchain.pem',
        'local_pk' => '/etc/letsencrypt/live/'.DOMAIN.'/privkey.pem',
        'verify_peer' => FALSE
    )
));

I have found that verify_peer must be set to false in order for this code to work. PHP documentation shows that verify_peer defaults to true however Christian said that PHP's source sets verify_peer to false by default for server-side sockets.

if I omit verify_peer, the server runs displaying no errors. When I try to connect from the browser the websocket just shows finished.

PHP 7.4.9
"react/socket": "^1.6",

@michaelphipps Thanks for reporting here, this is an interesting one indeed!

I agree the verify_peer setting should default to true for outgoing client connections and should default to false for incoming server connections.

The PHP documentation indeed currently claims that veriy_peer defaults to true, but checking PHP's source code, this actually only holds true for client sockets: https://github.com/php/php-src/blob/cd0cd3d31ee5e1b0f2cd8899b754a03578b5caef/ext/openssl/xp_ssl.c#L513

This means that verify_peer correctly defaults to false for server connections as expected (but unlike documented). In fact, this is also covered by our existing test suite, e.g.

public function testClientCanConnectToServer()
{
$loop = Factory::create();
$server = new TcpServer(0, $loop);
$server = new SecureServer($server, $loop, array(
'local_cert' => __DIR__ . '/../examples/localhost.pem'
));
$connector = new SecureConnector(new TcpConnector($loop), $loop, array(
'verify_peer' => false
));
$promise = $connector->connect($server->getAddress());
/* @var ConnectionInterface $client */
$client = Block\await($promise, $loop, self::TIMEOUT);
$this->assertInstanceOf('React\Socket\ConnectionInterface', $client);
$this->assertEquals($server->getAddress(), $client->getRemoteAddress());
$client->close();
$server->close();
}

I have found that verify_peer must be set to false in order for this code to work. PHP documentation shows that verify_peer defaults to true however Christian said that PHP's source sets verify_peer to false by default for server-side sockets.

if I omit verify_peer, the server runs displaying no errors. When I try to connect from the browser the websocket just shows finished.

As described above, I can not reproduce the problem you're seeing and also don't see how this could happen. This is covered by the existing test suite across all supported PHP versions, so this is known to work on a variety of platforms. If you're sure this problem persists, may I ask you to provide a gist to reproduce and/or a PR with a failing test case?

I believe this has been answered, so I'm closing this for now. Please come back with more details if this problem persists and we can always reopen this 👍