如何使用Apache中的ssl为外部脚本配置Laravel Websockets服务器

问题描述

我有一个由laravel-websockets为laravel应用制作的套接字服务器,通过普通的ws我可以使用laravel-echo在网页和外部node.js脚本中建立连接,一切都很好。问题来自ssl。该站点正在使用apache,并且在laravel-websockets中,documantation缺少这种ssl集成,但是找到了一些针对apache的反向代理的解决方案。反向代理仍然适用于正常连接,但不适用于外部node.js脚本-保持控制台日志unavailable

我的配置有问题或也需要做其他事情。

  • 反向代理的虚拟主机子域conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerAdmin admin@admin.com
    ServerName socket.my-domain.com
    ServerAlias www.socket.my-domain.com

    SSLEngine on
    SSLProxyEngine on
    SSLProxyVerify none
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    SSLProxyCheckPeerExpire off

SSLCertificateFile /etc/letsencrypt/live/socket.my-domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/socket.my-domain.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf

  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>

  <Location />
    RewriteEngine on
    RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
    RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
    RewriteRule .* ws://127.0.0.1:40126%{REQUEST_URI} [P,L]

    ProxyPass http://127.0.0.1:40126/
    ProxyPassReverse http://127.0.0.1:40126/
  </Location>


</VirtualHost>
</IfModule>

    'pusher' => [
                'driver' => 'pusher','key' => env('PUSHER_APP_KEY'),'secret' => env('PUSHER_APP_SECRET'),'app_id' => env('PUSHER_APP_ID'),'options' => [
                    'cluster' => env('PUSHER_APP_CLUSTER'),'useTLS' => false,'encrypted' => true,'host' => env('WEBSOCKET_HOST'),'port' => env('LaraVEL_WEBSOCKETS_PORT'),'scheme' => 'http','curl_options' => [
                        CURLOPT_SSL_VERIFYHOST => 0,CURLOPT_SSL_VERIFYPEER => 0,],]
  • websockets.PHP
        [
            'id' => env('PUSHER_APP_ID'),'name' => env('APP_NAME'),'path' => env('PUSHER_APP_PATH'),'capacity' => null,'enable_client_messages' => true,'enable_statistics' => true,...
'ssl' => [
        /*
         * Path to local certificate file on filesystem. It must be a PEM encoded file which
         * contains your certificate and private key. It can optionally contain the
         * certificate chain of issuers. The private key also may be contained
         * in a separate file specified by local_pk.
         */
        'local_cert' => env('LaraVEL_WEBSOCKETS_SSL_LOCAL_CERT',null),/*
         * Path to local private key file on filesystem in case of separate files for
         * certificate (local_cert) and private key.
         */
        'local_pk' => env('LaraVEL_WEBSOCKETS_SSL_LOCAL_PK',/*
         * Passphrase for your local_cert file.
         */
        'passphrase' => env('LaraVEL_WEBSOCKETS_SSL_PAsspHRASE','verify_peer' =>  false,]

  • .env
broADCAST_DRIVER=pusher
PUSHER_APP_ID=123456
PUSHER_APP_SECRET=ituc16ngcf
PUSHER_APP_KEY=zns8tgs6r91
PUSHER_APP_CLUSTER=mt1
WEBSOCKET_HOST=127.0.0.1
LaraVEL_WEBSOCKETS_PORT=40126
WEBSOCKETS_URL=socket.my-domain.com
  • 外部node.js脚本
global.Pusher = require('pusher-js');
global.Echo = require('laravel-echo');

global.broadcast_auth_path = 'some_auth_link';
global.token = "some authorized token";
global.broadcast_auth_headers = {
    headers: {
        Authorization: "Bearer " + token
    }
};

var echoConfig = {
    broadcaster: 'pusher',key: 'zns8tgs6r91',cluster: 'mt1',wsHost: 'socket.my-domain.com',wsPort: 80,wssport = 443,authEndpoint: broadcast_auth_path,auth: { ... broadcast_auth_headers },forceTLS: true,encrypted: true,disableStats: true,enabledTransports: [ 'wss','ws'],}
Pusher.logToConsole = true;

Echo = new Echo(echoConfig);

Echo.connector.pusher.connection.bind( 'error',function( err ) {
    console.log(err);
});

Echo.connector.pusher.connection.bind('connected',function( ) {
    console.log('connected');
});

Echo.connector.pusher.connection.bind('disconnected',function( ) {
    console.log('disconnected');
});

Echo.connector.pusher.connection.bind('connecting',function( ) {
    console.log('connecting');
});
Echo.connector.pusher.connection.bind('initialized',function( ) {
    console.log('initialized');
});
Echo.connector.pusher.connection.bind('unavailable',function() {
    console.log('unavailable');
});
Echo.connector.pusher.connection.bind('Failed',function( ) {
    console.log('Failed');
});
  • 套接字服务器启动命令 PHP artisan websockets:serve --host=127.0.0.1 --port=40126

解决方法

问题是,pusher-js(用于nodejs)的websockets集成使来自dns的指向ip地址出现问题,这导致ssl altname仅按字母顺序指向第一个子域(在我的情况下是错误的)。

一种简单的解决方案是在第一个字母排序之前先创建一个新的子域反向代理(前面带有双aa的aawss),然后一切顺利进行。