alp*_*am8 16 php ssl serversocket websocket phpwebsocket
我试图连接到由PHP创建的安全websocket,但由于某种原因它不起作用.证书文件对于PHP是可读的.
到目前为止,这是我的代码(PHP方面;为简单起见,剥离代码):
$context = stream_context_create();
stream_context_set_option($context, 'ssl', 'allow_self_signed', false);
stream_context_set_option($context, 'ssl', 'verify_peer', true);
stream_context_set_option($context, 'ssl', 'peer_name', 'example.com');
stream_context_set_option($context, 'ssl', 'CN_match', 'example.com');
stream_context_set_option($context, 'ssl', 'SNI_enabled', true);
stream_context_set_option($context, 'ssl', 'local_cert', '/path/to/ssl/cert/example.com');
stream_context_set_option($context, 'ssl', 'local_pk', '/path/to/ssl/private/example.com');
$serverSocket = stream_socket_server(
'tls://example.com:8090',
$errNo,
$errStr,
\STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN,
$context
);
$client = stream_socket_accept($serverSocket);
// send initial websocket connection stuff
$request = socket_read($client, 5000);
preg_match('#Sec-WebSocket-Key: (.*)\r\n#', $request, $matches);
$key = base64_encode(pack(
'H*',
sha1($matches[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
));
$headers = "HTTP/1.1 101 Switching Protocols\r\n";
$headers .= "Upgrade: websocket\r\n";
$headers .= "Connection: Upgrade\r\n";
$headers .= 'Sec-WebSocket-Version: 13' . "\r\n";
$headers .= 'Sec-WebSocket-Accept: ' . $key . "\r\n\r\n";
socket_write($client, $headers, \mb_strlen($headers));
// do something here...
socket_close($client);
socket_close($serverSocket);
Run Code Online (Sandbox Code Playgroud)
客户方:
var con = new WebSocket('wss://' + host + ':' + port);
var $chat = $('#chat');
con.onmessage = function(e) {
$chat.append('<p>' + e.data + '</p>');
};
con.onopen = function(e) {
con.send('Hello Me!');
};
con.onclose = function (e) {
console.log('connection closed.', arguments);
}
Run Code Online (Sandbox Code Playgroud)
我没有任何*.pem文件.只是apache web服务器中使用的两个文件.如果需要,可以将该文件转换为pem文件.但我认为它应该在php中使用这两个文件,不应该吗?
为了更好的测试,我们使用带有let的加密证书的隔离子域.因为我们可以完全访问此服务器.但是,从certifacte生成器我只得到了那两个提到的文件.对于Web服务器,它可以很好地工作.但是如何为php中的websocket做同样的事情呢?
现在,使用此代码,在向客户端发送一些消息后,服务器脚本告诉我,它无法从证书中获取对等方.我不知道这条消息的含义以及如何解决这个问题.我也试过alreay交换local_cert和local_pk互相,但它并没有帮助反正.
编辑:经过一段时间的研究,事实证明,PHP失败了每一个组合与另一个错误.
我生成的证书文件如下所示:
文件/ opt/psa/var/certificates/cert-0x8zHR:
-----BEGIN CERTIFICATE REQUEST-----
some letters
-----END CERTIFICATE REQUEST-----
-----BEGIN PRIVATE KEY-----
some letters
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
some letters
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
some letters
-----END CERTIFICATE-----
Run Code Online (Sandbox Code Playgroud)
文件/ opt/psa/var/certificates/cert-Du9H8N:
-----BEGIN CERTIFICATE-----
some letters
-----END CERTIFICATE-----
Run Code Online (Sandbox Code Playgroud)
来自两个证书字符串的所有行都在字符位置65处结束.
正如你可以在php文档中看到的那样,php希望得到一个PEM格式的文件:http://php.net/manual/en/context.ssl.php#context.ssl.local-cert
我发现本教程将我的两个文件转换为一个PEM文件,但我的证书看起来与网站上提到的不同,而且我不知道究竟要包含在PEM文件中,PHP需要:https:// www. digicert.com/ssl-support/pem-ssl-creation.htm
编辑2:如下所述,这里是我得到的确切错误:
同
stream_context_set_option($cont, 'ssl', 'local_pk', '/opt/psa/var/certificates/cert-0x8zHR');
stream_context_set_option($cont, 'ssl', 'local_cert', '/opt/psa/var/certificates/cert-Du9H8N');
Run Code Online (Sandbox Code Playgroud)
警告:stream_socket_accept():无法在...中设置私钥文件`/ opt/psa/var/certificates/cert-0x8zHR'...
警告:stream_socket_accept():无法在...中启用加密...
警告:stream_socket_accept():接受失败:成功...在线......
警告:socket_read()期望参数1是资源,boolean在...中给出...
注意:未定义的偏移量:1 ...在线...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_close()期望参数1是资源,在线...给出的布尔值...
与
stream_context_set_option($cont, 'ssl', 'local_cert', '/opt/psa/var/certificates/cert-0x8zHR');
stream_context_set_option($cont, 'ssl', 'local_pk', '/opt/psa/var/certificates/cert-Du9H8N');
Run Code Online (Sandbox Code Playgroud)
警告:stream_socket_accept():无法在...中设置私钥文件`/ opt/psa/var/certificates/cert-Du9H8N'...
警告:stream_socket_accept():无法在...中启用加密...
警告:stream_socket_accept():接受失败:成功...在线......
警告:socket_read()期望参数1是资源,boolean在...中给出...
注意:未定义的偏移量:1 ...在线...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_close()期望参数1是资源,在线...给出的布尔值...
并且(只是cert-0x8zHR与cert-Du9H8N的串联)
$file = dirname(__FILE__, 3) . \DIRECTORY_SEPARATOR . 'fullchain.pem';
stream_context_set_option($cont, 'ssl', 'local_cert', $file);
Run Code Online (Sandbox Code Playgroud)
警告:stream_socket_accept():无法获得对等证书......
警告:stream_socket_accept():无法启用加密......
警告:stream_socket_accept():接受失败:成功......
警告:socket_read()期望参数1是资源,boolean在...中给出...
注意:未定义的偏移量:1 ...在线...
警告:socket_write()期望参数1是资源,在线...给出的布尔值...
警告:socket_write()期望参数1是资源,boolean在...中给出
警告:socket_write()期望参数1是资源,boolean在...中给出
警告:socket_write()期望参数1是资源,boolean在...中给出
警告:socket_write()期望参数1是资源,boolean在...中给出
警告:socket_write()期望参数1是资源,boolean在...中给出
警告:socket_close()期望参数1是资源,在线...给出的布尔值...
编辑3:是的,的确有一个openssl错误.在第三次socket_stream_accept警告后,我现在通过使用php doc示例中的代码得到此错误:
error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch
Run Code Online (Sandbox Code Playgroud)
我在互联网上搜索了这个错误.他们说,如果出现此错误,我选择了错误的证书文件.
另外,如果我播放此命令:
openssl x509 -noout -in cert-0x8zHR -modulus
Run Code Online (Sandbox Code Playgroud)
模数有两个不同的字符串.但我不知道为什么,也不知道如何解决这个问题.这两个文件都在apache web server vhost config中使用,它可以正常工作:
SSLEngine on
SSLVerifyClient none
SSLCertificateFile /opt/psa/var/certificates/cert-0x8zHR
SSLCACertificateFile /opt/psa/var/certificates/cert-Du9H8N
Run Code Online (Sandbox Code Playgroud)
PS:如果你知道任何本地转换为pem文件的工具,请告诉我.在线转换是不可能的.
OpenSSL 似乎不喜欢您的密钥。
您可以尝试致电http://php.net/manual/en/function.openssl-error-string.php看看是否有更多关于原因的信息?
或者尝试不同的关键文件组合,根据这些可能相关的问题,这些问题具有相同的错误:
GL