Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I get a SSL error swSSL_connection_error (ERRNO 1014) #2717

Closed
m3m0r7 opened this issue Jul 27, 2019 · 25 comments
Closed

I get a SSL error swSSL_connection_error (ERRNO 1014) #2717

m3m0r7 opened this issue Jul 27, 2019 · 25 comments
Labels
in progress Maintainers are working on this waiting for user action

Comments

@m3m0r7
Copy link

m3m0r7 commented Jul 27, 2019

Please answer these questions before submitting your issue. Thanks!

  1. What did you do? If possible, provide a simple script for reproducing the error.
  • I get many errors which is shown below.
  • It is shown error when sending an image data (about 8KB) to SSL connected client.
NOTICE	swSSL_connection_error (ERRNO 1014): SSL connection#0[IP:Port] protocol error[127]
  • I'm using Let's encrypt certification file.

Short Script.

go(function () use ($packet, $channel, $synchronizer) {
...
    $data = 'data:image/jpeg;base64,' . base64_encode($packet);

    for ($i = 1, $chunks = str_split($data, $client->getChunkSize()), $loops = count($chunks); $i <= $loops; $i++) {
        $client
            ->enableBuffer(false)
            ->enableChunk(false)
            ->write(
                WebSocket::encodeMessage(
                    $client,
                    $chunks[$i - 1],
                    $i === 1
                        ? WebSocket::OPCODE_MESSAGE
                        : WebSocket::OPCODE_CONTINUATION,
                    $i === $loops
                )
            );
    }
}
...
  • $packet is an image data.

  • It is encoding text with WebSocket RFC.

Full code is here: https://github.com/memory-agape/magnolia-server/blob/master/src/magnolia/Client/Camera.php#L103

  1. What did you expect to see?
    Don't show errors.

  2. What did you see instead?

  3. What version of Swoole are you using (show your php --ri swoole)?

swoole

Swoole => enabled
Author => Swoole Team <[email protected]>
Version => 4.4.2
Built => Jul 27 2019 15:27:18
coroutine => enabled
epoll => enabled
eventfd => enabled
signalfd => enabled
cpu_affinity => enabled
spinlock => enabled
rwlock => enabled
openssl => OpenSSL 1.0.2k-fips  26 Jan 2017
http2 => enabled
pcre => enabled
zlib => enabled
mutex_timedlock => enabled
pthread_barrier => enabled
futex => enabled
async_redis => enabled
  1. What is your machine environment used (including version of kernel & php & gcc) ?
    OS: CentOS 7 on Docker
PHP 7.3.7 (cli) (built: Jul  3 2019 11:30:22) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.7, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.7, Copyright (c) 1999-2018, by Zend Technologies

Details is here: https://github.com/memory-agape/magnolia-server/blob/master/infra/php/Dockerfile

@twose
Copy link
Member

twose commented Jul 28, 2019

It's just a guess: If you use IP directly instead of hostname, try $client->set(['ssl_hostname' => $hostname])
If not, you may need to provide more information

@twose twose added the in progress Maintainers are working on this label Jul 28, 2019
@m3m0r7
Copy link
Author

m3m0r7 commented Jul 28, 2019

Thanks for your replying 🙏

No, I'm not connected with IP address directly.

you may need to provide more information

Okay, What like you need information?
I write information as much as possible.

In server-side

  • I'm using go coroutine only. (I'm not using \Swoole\WebSocket\Server\XXXX classes)
  • My stream_context_set_option is here.
stream_context_set_option(
    $context,
    'ssl',
    'local_cert',
    '/path/to/file'
);
stream_context_set_option(
    $context,
    'ssl',
    'local_pk',
    '/path/to/file'
);
stream_context_set_option(
    $context,
    'ssl',
    'allow_self_signed',
    true
);
stream_context_set_option(
    $context,
    'ssl',
    'verify_peer',
    false
);
stream_context_set_option(
    $context,
    'ssl',
    'verify_peer_name',
    false
);

Full code is here: https://github.com/memory-agape/magnolia-server/blob/master/src/magnolia/Traits/SecureConnectionManageable.php#L13

  • I'm using stream_socket_enable_crypto for encryption with SSL

Server

$server = stream_socket_server(
    sprintf(
        ($this->isEnabledTLS() ? 'tls' : 'tcp') . '://%s:%d',
        $this->getListenHost(),
        $this->getListenPort(),
    ),
    $errno,
    $errstr,
    STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
    $context
);
stream_socket_enable_crypto($server, false);

Connect accepting:

while ($client = @stream_socket_accept($server, 0)) {
    if ($this->isEnabledTLS()) {
        stream_socket_enable_crypto(
            $client,
            true,
            STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
        );
    }
...

https://github.com/memory-agape/magnolia-server/blob/master/src/magnolia/Server/GenericServer.php#L65

  • I'm implementing WebSocket server and HTTPS server myself.

    • The error is shown only when connecting with a WebSocket server (wss://hostname)
    • But, HTTPS is not shown the error.
  • The WebSocket server send data which is chunked 8KB.

  • Servers mixed to allow secure connection and non-secure connection. (Original Protocol, https and wss)

Detail code is here: https://github.com/memory-agape/magnolia-server/blob/master/src/magnolia/Server/GenericServer.php

stream_get_meta_data($client) is shown below:

php      | array(8) {
php      |   ["crypto"]=>
php      |   array(4) {
php      |     ["protocol"]=>
php      |     string(7) "UNKNOWN"
php      |     ["cipher_name"]=>
php      |     string(17) "AES128-GCM-SHA256"
php      |     ["cipher_bits"]=>
php      |     int(128)
php      |     ["cipher_version"]=>
php      |     string(11) "TLSv1/SSLv3"
php      |   }
php      |   ["timed_out"]=>
php      |   bool(false)
php      |   ["eof"]=>
php      |   bool(false)
php      |   ["blocked"]=>
php      |   bool(true)
php      |   ["stream_type"]=>
php      |   string(20) "tcp_socket/coroutine"
php      |   ["mode"]=>
php      |   string(2) "r+"
php      |   ["unread_bytes"]=>
php      |   int(0)
php      |   ["seekable"]=>
php      |   bool(false)
php      | }

In client-side

A packet data is: 32byte + 8byte + ImageData(N byte)

bytes(os.environ.get("AUTH_KEY", "").encode('utf-8')) + pack("L", len(frame)) + frame

@twose
Copy link
Member

twose commented Jul 29, 2019

I got it.
I am afraid our wrapper has not implemented some of the SSL options.
but Swoole\Coroutine\Socket supported these options, It may take a little time to wrap it, because very few people use this API, so we forgot it.

@twose
Copy link
Member

twose commented Jul 29, 2019

I will add some patches for SSL gradually

@m3m0r7
Copy link
Author

m3m0r7 commented Jul 29, 2019

Okay, Thanks twose!
And I'll try to implement a server with Swoole\Coroutine\Socket 🙏

twose added a commit that referenced this issue Jul 30, 2019
@twose
Copy link
Member

twose commented Jul 30, 2019

I just read the ssl options of context directly, then passed it to SW_API
I don't know much about php native options, may take some time to do it better

or you can:

stream_context_set_option(
    $context,
    'swoole',
    'swoole_option_name',
    $value
);

@m3m0r7
Copy link
Author

m3m0r7 commented Jul 30, 2019

OK, I'll try it.

@twose
Copy link
Member

twose commented Jul 31, 2019

I removed the swoole context support after team discussion, and I rewrote the php ssl options to swoole:

SSL_OPTION_ALIAS("peer_name", "ssl_hostname");
SSL_OPTION_ALIAS("verify_peer", "ssl_verify_peer");
SSL_OPTION_ALIAS("allow_self_signed", "ssl_allow_self_signed");
SSL_OPTION_ALIAS("cafile", "ssl_cafile");
SSL_OPTION_ALIAS("capath", "ssl_capath");
SSL_OPTION_ALIAS("local_cert", "ssl_cert_file");
SSL_OPTION_ALIAS("local_pk", "ssl_key_file");
SSL_OPTION_ALIAS("passphrase", "ssl_passphrase");
SSL_OPTION_ALIAS("verify_depth", "ssl_verify_depth");
SSL_OPTION_ALIAS("disable_compression", "ssl_disable_compression");

The above options ​​are supported now

You can close the issue if your application can work well, or continue to post questions

@m3m0r7
Copy link
Author

m3m0r7 commented Jul 31, 2019

Thanks! Twose. Hmm... but, I'm still getting the error...

I changed Dockerfile:

RUN git clone https://github.com/swoole/swoole-src.git
RUN cd swoole-src && \
    git checkout master && \
    phpize && \
    ./configure --enable-openssl && \
    make && \
    make install

On the one hand, I'm replacing PHP native stream to \Swoole\Server.
I'll use it if it does not show the error.

@m3m0r7 m3m0r7 closed this as completed Jul 31, 2019
@m3m0r7 m3m0r7 reopened this Jul 31, 2019
@twose
Copy link
Member

twose commented Aug 1, 2019

stream_socket_enable_crypto what is it for?

@twose
Copy link
Member

twose commented Aug 1, 2019

Swoole does not support disable SSL dynamically

@m3m0r7
Copy link
Author

m3m0r7 commented Aug 1, 2019

In those days, I read this example for implementing my application. (but I knew that is unnecessary when using tls://.)
https://www.leenix.co.uk/news-howto-php-tcp-serverclient-with-ssl-encryption-using-streams-8

it is removed in my environment, but it is still getting the error.

@m3m0r7
Copy link
Author

m3m0r7 commented Aug 1, 2019

I built a docker-image with latest master.
The error greatly reduced. but the error is remaining a few.

The error show when fwrite return value is incorrect (Does not match actual value length and wrote length).

            $wroteLength = fwrite($this->stream, $this->buffers);
            if ($wroteLength < strlen($this->buffers)) {
                echo 'Try to send: ' . implode(' ', str_split(bin2hex($this->buffers), 2)) . "\n";
            }
            echo 'Sent buffers: ' . ($wroteLength . '/' . strlen($this->buffers)) . "\n";

Added here: https://github.com/memory-agape/magnolia-server/blob/2d9de768c6f1f51432c479cd34aa5248f4203589/src/magnolia/Stream/Stream.php#L103

Output is shown below when the error has been shown.

php      | [2019-08-01 16:00:18 @29.0]	NOTICE	swSSL_connection_error (ERRNO 1014): SSL connection#0[172.24.0.1:43626] protocol error[127]
php      | Try to send: 00 7e 20 00 58 4e 4d 31 4f 42 52 61 47 35 31 4e 6e 41 5a 62 65 33 6a 4f 49 2b 4d 6a ... 35 38 43 66 73 65 36 5a 59 72 48 63 2b 4a 37
php      | Sent buffers: 0/8196

@twose
Copy link
Member

twose commented Aug 2, 2019

You can use stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLSv1_2_SERVER); but you can't use stream_socket_enable_crypto($server, false);

twose added a commit that referenced this issue Aug 2, 2019
@twose
Copy link
Member

twose commented Aug 2, 2019

I tried to support the SSL dynamic switching, can you have a try

@twose
Copy link
Member

twose commented Aug 2, 2019

All SSL proto errors are due to the underlying SSL handshake

@m3m0r7
Copy link
Author

m3m0r7 commented Aug 2, 2019

Thanks, I'll try it.

@m3m0r7
Copy link
Author

m3m0r7 commented Aug 2, 2019

I tried it.
I see that crypto.protocol is changed UNKNOWN to TLSv1.2.

Unfortunately, I'm still getting the error.... 😭
And, furthermore, the error is very increasing shown.

php      | [2019-08-02 13:14:32 @29.0]	NOTICE	swSSL_connection_error (ERRNO 1014): SSL connection#0[172.24.0.1:40282] protocol error[127]
php      | array(8) {
php      |   ["crypto"]=>
php      |   array(4) {
php      |     ["protocol"]=>
php      |     string(7) "TLSv1.2"
php      |     ["cipher_name"]=>
php      |     string(17) "AES128-GCM-SHA256"
php      |     ["cipher_bits"]=>
php      |     int(128)
php      |     ["cipher_version"]=>
php      |     string(11) "TLSv1/SSLv3"
php      |   }
php      |   ["timed_out"]=>
php      |   bool(false)
php      |   ["eof"]=>
php      |   bool(false)
php      |   ["blocked"]=>
php      |   bool(true)
php      |   ["stream_type"]=>
php      |   string(20) "tcp_socket/coroutine"
php      |   ["mode"]=>
php      |   string(2) "r+"
php      |   ["unread_bytes"]=>
php      |   int(0)
php      |   ["seekable"]=>
php      |   bool(false)
php      | }

Screen Shot 2019-08-02 at 22 25 07

@twose
Copy link
Member

twose commented Aug 3, 2019

@memory-agape
I just saw your code, try to call stream_context_set_option first, then enable SSL

@m3m0r7
Copy link
Author

m3m0r7 commented Aug 3, 2019

If my understanding is mistaken, please tell me.

I just changed code here:

//            $context = stream_context_create();
//
//            if ($this->isEnabledTLS()) {
//                // Write SSL Context
//                $this->writeTLSContext($context);
//            }

            $server = stream_socket_server(
                sprintf(
                    'tcp://%s:%d',
                    $this->getListenHost(),
                    $this->getListenPort(),
                ),
                $errno,
                $errstr,
                STREAM_SERVER_BIND | STREAM_SERVER_LISTEN
            );
// ...
            while (true) {
                try {
                    while ($client = @stream_socket_accept($server, 0)) {
                        if ($this->isEnabledTLS()) {
                            // Write SSL Context

                            $this->writeTLSContext($client);

                            stream_context_set_option(
                                $client,
                                'ssl',
                                'peer_name',
                                'magnolia-client.test'
                            );

                            stream_socket_enable_crypto(
                                $client,
                                true,
                                STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
                            );
                        }

It output is shown below:

php      | [2019-08-03 06:15:26 @29.0]	WARNING	swSSL_connect: SSL_connect(fd=14) failed. Error: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol[1|252]

And I changed STREAM_CRYPTO_METHOD_TLSv1_2_SERVER to STREAM_CRYPTO_METHOD_SSLv23_SERVER, it is not affected.


By the way, I got SEGV with below code.

            if ($this->isEnabledTLS()) {
                // Write SSL Context
                $this->writeTLSContext($context);
            }

            $server = stream_socket_server(
                sprintf(
                    'tls://%s:%d',
                    $this->getListenHost(),
                    $this->getListenPort(),
                ),
                $errno,
                $errstr,
                STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
                $context
            );
// ...
            while (true) {
                try {
                    while ($client = @stream_socket_accept($server, 0)) {
                        if ($this->isEnabledTLS()) {
                            // Write SSL Context

                            $this->writeTLSContext($client);

                            stream_context_set_option(
                                $client,
                                'ssl',
                                'peer_name',
                                'magnolia-client.test'
                            );

                            stream_socket_enable_crypto(
                                $client,
                                true,
                                STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
                            );
                        }

It seems that duplicate enabling SSL. (this is a guess.)

@twose
Copy link
Member

twose commented Aug 3, 2019

can you run USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php xxx.php and show me the log, I want to know why the application coredump

@twose
Copy link
Member

twose commented Aug 3, 2019

https://github.com/swoole/swoole-src/blob/master/tests/swoole_runtime/ssl_server.phpt

I don't see the problem with your example, you can refer to the example above, try to reproduce this problem with the simplest code

@m3m0r7
Copy link
Author

m3m0r7 commented Aug 3, 2019

The first problem memory dump is here:
https://gist.github.com/memory-agape/435e808adbd0f185fd04c7d1e2477525

The SEGV problem did not show when using USE_ZEND_ALLOC=0 env.
Disabled USE_ZEND_ALLOC=0 memory dump is here:
https://gist.github.com/memory-agape/8c566ca63ac37855f3a141ab8e07c426

I don't see the problem with your example, you can refer to the example above, try to reproduce this problem with the simplest code

OK, It may take time 🙏

@twose
Copy link
Member

twose commented Aug 4, 2019

The log shows that the memory error originated from PHP's memory manager... It's rare, and I generally think that this is caused by something else...

@m3m0r7
Copy link
Author

m3m0r7 commented Aug 4, 2019

Are you talking about SEGV?

And, I'm trying to reproduce the problem with simplest code.
Please wait a little longer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in progress Maintainers are working on this waiting for user action
Projects
None yet
Development

No branches or pull requests

3 participants