laravel-websockets icon indicating copy to clipboard operation
laravel-websockets copied to clipboard

Problem with config wss, certs, etc

Open ssheduardo opened this issue 3 years ago • 16 comments

First of all, many thanks to the team for making this package possible. I will detail the exact steps I take to try to configure the wss.

My configuration

- Laravel 5.7
- beyondcode/laravel-websockets 1.3.0
- pusher/pusher-php-server 4.1.5

Nginx with proxy reverse

location /app {
        proxy_pass             http://127.0.0.1:6001;
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

STEP

  1. I have created a domain without https.
  2. Config websockets.php and broadcasting.php (simple config)
  3. I have uploaded the project and it works without problem, I can enter the panel and see the statistics.
  4. Seeing that everything works perfectly.

NOW, ACTIVATE WSS

STEP I should mention that I have read and tested many tutorials and issues here.

  1. I have created some certificates on my server with this command. sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/websockets-selfsigned.key -out /etc/ssl/certs/websockets-selfsigned.crt
  2. Open file config/websockets.php and the configuration
....
....
'apps' => [
        [
            'id' => env('PUSHER_APP_ID'),
            'name' => env('APP_NAME'),
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            '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('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('LOCAL_KEY', null),

        /*
         * Passphrase with which your local_cert file was encoded.
         */
        'passphrase' => null,
        'verify_peer' => false,
        'allow_self_signed' => true,
    ],

My .ENV

PUSHER_APP_ID=666666
PUSHER_APP_KEY='AAbLk31NuAA'
PUSHER_APP_SECRET='VV6dfnj6K32aCNuFa'
PUSHER_APP_CLUSTER=mt1
PUSHER_SCHEME='https'

LOCAL_CERT='/etc/ssl/certs/websockets-selfsigned.crt'
LOCAL_KEY='/etc/ssl/private/websockets-selfsigned.key'
LOCAL_PEM='/etc/ssl/certs/websockets-selfsigned.pem'

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
  1. Open file config/brodcasting.php and the configuration
'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'),
                'encrypted' => true,
                'useTLS' => true,
                'host' => '127.0.0.1',
                'port' => 6001,
                'scheme' => env('PUSHER_SCHEME'),
                'curl_options' => [
                    CURLOPT_SSL_VERIFYHOST => 0,
                    CURLOPT_SSL_VERIFYPEER => 0,
                ],
            ],
        ],
  1. Add config for nginx.ssl.conf (Port 443)
location /app {
        proxy_pass             https://127.0.0.1:6001;        
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
  1. Restart nginx
  2. Now Testing laravel-websockets panel and fail.

WebSocket connection to 'wss://websockets.ubublog.com:80/app/ygbLk87NuyN?protocol=7&client=js&version=4.3.1&flash=false' failed:

image


I have followed all the steps as per various tutorials and reviews here and I get this error. If anyone has managed to get wss working, can you tell me where I am going wrong. The steps are simple but there is something wrong with setting it up.

ssheduardo avatar May 18 '22 11:05 ssheduardo

I'm facing the same issue: beyondcode/laravel-websockets": "^1.13", "laravel/framework": "^7.24", "pusher/pusher-php-server": "~4.0"

zmoukit avatar May 26 '22 10:05 zmoukit

I don't understand why something so "EASY" to configure is so difficult.

ssheduardo avatar May 26 '22 19:05 ssheduardo

Try port 443, port 80 won't be using the SSL config so is likely what is causing the WSS connection to fail

lukehebb avatar Jun 01 '22 09:06 lukehebb

Try port 443, port 80 won't be using the SSL config so is likely what is causing the WSS connection to fail

I try with port 443 some error.

It is really so "COMPLICATED" to install it or give support, I do not believe that anyone does not work the WSS, it is impossible, I ask the community who has it configured can help us with this.

ssheduardo avatar Jun 01 '22 09:06 ssheduardo

We use WSS successfully for thousands of clients though we do it in a slightly different way as we use V2 of laravel-websockets behind a load balancer. One thing I can see is you are using a self-signed certificate so it may be best to replace that with one issued by letsencrypt instead as it could also be your browser not liking the self-signed cert

As you are using nginx to proxy the connections, you can remove the SSL config from the socket application instead and purely handle SSL within nginx, then let nginx proxy to the websocket service without SSL as its handled locally on the machine so will be safe

lukehebb avatar Jun 01 '22 09:06 lukehebb

We use WSS successfully for thousands of clients though we do it in a slightly different way as we use V2 of laravel-websockets behind a load balancer. One thing I can see is you are using a self-signed certificate so it may be best to replace that with one issued by letsencrypt instead as it could also be your browser not liking the self-signed cert

As you are using nginx to proxy the connections, you can remove the SSL config from the socket application instead and purely handle SSL within nginx, then let nginx proxy to the websocket service without SSL as its handled locally on the machine so will be safe

I currently have my site: www.demo.com with let'sEncrypt. Now from what I understood you say that inside the proxy stop using wss and instead ws.

What I don't understand is how if from a client X I make the call to ws from outside, that is insecure. That's the part I don't understand how to do that, can't you provide a practical example of how to do it by having a domain with HTTPS but calling ws?

Translated with www.DeepL.com/Translator (free version)

ssheduardo avatar Jun 01 '22 10:06 ssheduardo

We have it so our clients use wss://domain.com which runs nginx to accept SSL on port 443. This then uses nginx to proxy to the laravel-websockets application under the hood

Within the websockets application we don't configure SSL at all

For our laravel echo clients we use this config

window.Echo = new Echo({ broadcaster: 'pusher', key: process.env.MIX_PUSHER_APP_KEY, wsHost: 'domain.tld', wsPort: 443, authEndpoint: "https://domain.tld/broadcasting/auth", disableStats: true, forceTLS: true });

lukehebb avatar Jun 01 '22 10:06 lukehebb

We have it so our clients use wss://domain.com which runs nginx to accept SSL on port 443. This then uses nginx to proxy to the laravel-websockets application under the hood

Within the websockets application we don't configure SSL at all

For our laravel echo clients we use this config

window.Echo = new Echo({ broadcaster: 'pusher', key: process.env.MIX_PUSHER_APP_KEY, wsHost: 'domain.tld', wsPort: 443, authEndpoint: "https://domain.tld/broadcasting/auth", disableStats: true, forceTLS: true });

What you say makes more sense, I will try to do what you say, this information is very valuable.

ssheduardo avatar Jun 01 '22 10:06 ssheduardo

Hi, @lukehebb I have tried to make the changes but it has been impossible to make it work, I have tried to follow the steps more or less as you say but I have not succeeded. Can you please add an example of the configuration of nginx, websockets.php and brodcasting.php. I can't think what else to do and although you say you have installed in many clients the wss option, I would appreciate if you could share how you do it. Thanks

ssheduardo avatar Jun 10 '22 17:06 ssheduardo

Hello, @lukehebb

I've also been struggling to deploy Laravel WebSockets on live server.

After a lot of research I managed to get it to work over WSS successfully

but each time that I try to use it's dashboard, I need to open the link for wss connection in a new tab and access it by changing to https which means sending a GET request to the socket server.

I learned this from a tutorial video on Youtube but I'm not using a self signed certificate instead my laravel application is being served over apache with letsencrypt ssl certificate.

I also use CURLOPT_SSL_VERIFYHOST => 0 and CURLOPT_SSL_VERIFYPEER => 0, and when I remove it it doesn't work.

Why do I need to send a get request in order to activate wss ??????

Please tell me how to solve this issue.

gkia999 avatar Jul 05 '22 12:07 gkia999

If someone could make a video (youtube) using their own certificate or with letsencrypt, it would be ideal to get out of these doubts and avoid opening so many issues on this topic.

ssheduardo avatar Jul 05 '22 13:07 ssheduardo

I didn't open any issue on this topic, I just commented there with hope to find solutions for my problem or get some answer from someone regarding the issue.

I would appreciate if you could guide me, to understand the problem and debug the issue.

On Tue, Jul 5, 2022 at 4:59 PM Eduardo @.***> wrote:

If someone could make a video (youtube) using their own certificate or with letsencrypt, it would be ideal to get out of these doubts and avoid opening so many issues on this topic.

— Reply to this email directly, view it on GitHub https://github.com/beyondcode/laravel-websockets/issues/986#issuecomment-1175095034, or unsubscribe https://github.com/notifications/unsubscribe-auth/AM3RE5HBU3QQEDX2ZUUSYB3VSQ5TPANCNFSM5WIGORFQ . You are receiving this because you commented.Message ID: @.***>

gkia999 avatar Jul 05 '22 14:07 gkia999

I didn't open any issue on this topic, I just commented there with hope to find solutions for my problem or get some answer from someone regarding the issue. I would appreciate if you could guide me, to understand the problem and debug the issue. On Tue, Jul 5, 2022 at 4:59 PM Eduardo @.> wrote: If someone could make a video (youtube) using their own certificate or with letsencrypt, it would be ideal to get out of these doubts and avoid opening so many issues on this topic. — Reply to this email directly, view it on GitHub <#986 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AM3RE5HBU3QQEDX2ZUUSYB3VSQ5TPANCNFSM5WIGORFQ . You are receiving this because you commented.Message ID: @.>

I mean that it would be good that some of the people who have managed to run the wss in production with certificates either letsencrypt or other, make a video on youtube with the steps to follow, so we would not be opening issues with this problem.

ssheduardo avatar Jul 05 '22 14:07 ssheduardo

Yes, It would be great if there was such video available. I tried many things and managed to do it without proxypass or any additional config. I just had to recheck all config files did what was mentioned in the following links: issue #994 the comment from @booladsudan

gkia999 avatar Jul 05 '22 14:07 gkia999

I am using self-signed cert (with CA cert added into browser) and in my case I had to add following lines: 'ssl' => [ ... 'verify_peer' => false, 'verify_peer_name'=>false, 'allow_self_signed'=>true, ], into websockets.php to make it work.

ikopmans avatar Aug 14 '22 14:08 ikopmans

You could follow the configuration below this settings works for me both development and production:

In your broadcasting.php config file under the pusher object:

'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'),
                'host' => env('LARAVEL_WEBSOCKETS_HOST' , '127.0.0.1'),
                'port' => env('LARAVEL_WEBSOCKETS_PORT' , '6001'),
                'scheme' => env('LARAVEL_WEBSOCKETS_SCHEME' , 'http'),
                'encrypted' => env('LARAVEL_WEBSOCKETS_SECURE' , 'false'),
	        ],
        ],

Next, in your websockets.php config file try this:

'apps' => [
        [
            'id' => env('PUSHER_APP_ID'),
            'name' => env('APP_NAME'),
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            //'path' => env('PUSHER_APP_PATH'),
            'capacity' => null,
            'enable_client_messages' => false,
            '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', null),

        /*
         * Passphrase for your local_cert file.
         */
        'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),  

	    'verify_peer' => false,
    ],

And finally in your bootstrap.js (if you are using larave echo): This way you can dynamically use your websocket for development and production

let echoConfig = {
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    wsHost: window.location.hostname,
    wsPort: 6001,
    disableStats: true,
    forceTLS: false,
};

if(process.env.MIX_APP_ENV == 'production')
{
    echoConfig.enabledTransports = ['ws', 'wss'];
    echoConfig.wssPort = 6001;
    echoConfig.forceTLS = true;
}

Now of course let not forget to add the variables in the .env file:

for development just add these:

MIX_APP_ENV=local
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

for production add these:

LARAVEL_WEBSOCKETS_HOST="yourdomain.com"
LARAVEL_WEBSOCKETS_SCHEME=https
LARAVEL_WEBSOCKETS_SECURE=true
LARAVEL_WEBSOCKETS_PORT=6001
LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT=/etc/letsencrypt/live/yourdomain.com/fullchain.pem # if you are using letsencrypt
LARAVEL_WEBSOCKETS_SSL_LOCAL_PK=/etc/letsencrypt/live/yourdomain.com/privkey.pem # if you are using letsencrypt

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
MIX_APP_ENV=production

Be sure to clear cache and restart websocket

@gkia999 sorry I am not that good explain in videos but try to follow the above. Hope this helps.

booladsudan avatar Aug 24 '22 14:08 booladsudan