skip to Main Content

My development environment is this:

  • OS: Microsoft Windows 10
  • PHP framework: Laravel 8.0
  • PHP version 7.4
  • Websocket server: cboden/ratchet 0.4.3
  • WAMP server 3.2.0 (Apache 2.4.41)
  • Firefox 91.0.1 (64-bit) / chrome

I created a new Laravel app to implement a Secure Websocket Server and get connected to it using plain javascript on the client side (Laravel blade file).
The websocket server works fine, as far as I can see it running, but the web browser is not able to connect, as seen on this image:

enter image description here

I have tried using different URLs, with and without port number, but to no avail.
I created a SSL certificate and private key files, using openssl.exe tool, and put them in the command folder for testing purposes.

This is my handle code for the Secure Websocket Server:

   public function handle()
   {
      $loop   = Factory::create();
      $webSock = new SecureServer(
         new Server('0.0.0.0:8090', $loop),
         $loop,
         array(
            'local_cert'        => 'certificate.crt', 
            'local_pk'          => 'private.key', 
            'allow_self_signed' => TRUE, 
            'verify_peer' => FALSE
         )
      );

      // Ratchet magic
      $webServer = new IoServer(
         new HttpServer(
            new WsServer(
               new WebSocketController()
            )
         ),
         $webSock
      );

      $loop->run();
   }

My virtual host in httpd-ssl.conf file:

<VirtualHost *:443>
  ServerName ssa
  DocumentRoot "d:/web/app/ssa/public"
  SSLEngine on
  
  SSLCertificateFile "${SRVROOT}/conf/certificate.crt"
  SSLCertificateKeyFile "${SRVROOT}/conf/private.key"

  SSLVerifyClient none
  SSLVerifyDepth 10

  <Directory "d:/web/app/ssa/public">
    Options +Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require local
  </Directory>
  
  ProxyRequests Off 
  ProxyPass /wss/  ws://ssa:8090
</VirtualHost>

The Apache modules proxy_module, proxy_http_module and proxy_wstunnel_module are loaded.
The web app is running in HTTPS.
Before, it was running over HTTP and WS and everything worked perfectly, but I need to secure this app and I am having issues to connect to the secure websocket server.

Am I missing something?

Is there something wrong with my Websocket server or Apache configuration?

3

Answers


  1. Chosen as BEST ANSWER

    Ok, as @apokryfos pointed out, I tried to proxy the websocket server through HTTPS but I was doing it in the wrong way.

    I changed my websocket server to a non-secure one and did the following change to my virtual host:

    <VirtualHost *:443>
      ServerName ssa
      DocumentRoot "d:/web/app/ssa/public"
      SSLEngine on
      
      SSLCertificateFile "${SRVROOT}/conf/certificate.crt"
      SSLCertificateKeyFile "${SRVROOT}/conf/private.key"
    
      SSLVerifyClient none
      SSLVerifyDepth 10
    
      <Directory "d:/web/app/ssa/public">
        Options +Indexes +Includes +FollowSymLinks +MultiViews
        AllowOverride All
        Require local
      </Directory>
      
      Redirect /wss /wss/
      ProxyPass /wss/ ws://127.0.0.1:8090/
      ProxyPassReverse /ws/ wss://127.0.0.1:8090/
    </VirtualHost>
    

    On the client side, the browser can now contact the backend WS server through the HTTPS port:

    // The connection to the WebSocket Server.
    var socket = new WebSocket("wss://ssa:443/wss/");
    

    I got this solution from Apache Config: Websockets Proxy WSS request to WS backend

    Now I got my non-secure Websocket server sending/receiving through HTTPS. This is, for sure, not the solution I expected to apply to my needs but it certainly works. I still hope to find a formal solution to connecting plain JavaScript client to a Secure Websocket Server (wss://) without using a proxy mechanism.


  2. You are surely trying to connect to the wrong destination. It says wss:///ssa/wss/, but probably it should be wss://your.site.domain/ssa/wss/ .

    So let’s look at front end code and find out what’s wrong with it.

    Login or Signup to reply.
  3. For not to complicate my first answer with more information, here I provide the answer that really worked for me after all.

    I created the Secure Websocket Server as follows:

    public function handle() {
          $loop = Factory::create();
          $webSock = new SecureServer(
             new Server('0.0.0.0:8443', $loop),
             $loop,
             array(
                'local_cert' => 'C:/wamp64/bin/apache/apache2.4.41/conf/server.crt',
                'local_pk' => 'C:/wamp64/bin/apache/apache2.4.41/conf/server.key', 
                'allow_self_signed' => TRUE, 
                'verify_peer' => FALSE
             )
          );
          $webServer = new IoServer(
             new HttpServer(
                new WsServer(
                   new WebSocketController()
                )
             ),
             $webSock
          );
          $loop->run();
    }
    

    Note I changed the port number to 8443 (I don’t think this has something to do) and also changed the certificate and key files for the new ones, generated as follows:

    openssl req -config config.conf -new -x509 -out server.crt -days 3650

    And the config.conf file is:

    [req]
    default_bits = 2048
    encrypt_key = no
    default_md = sha256
    default_keyfile = server.key
    distinguished_name = req_distinguished_name
    prompt = no
    
    [req_distinguished_name]
    C = KH
    ST = Siem Reap
    L = SR
    O = AHC
    OU = IT
    CN = localhost
    
    [bs_section]
    CA=false
    

    All the difference lies in the last line CA=false to indicate I did not signed or acted as a Certificate Authority (CA).
    This gets rid of the MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY message.

    Then, I got rid of the lines that defined the proxy in my httpd-ssl.conf file:

    <VirtualHost *:443>
      ServerName ssa
      DocumentRoot "d:/web/app/ssa/public"
      SSLEngine on
      
      SSLCertificateFile "${SRVROOT}/conf/server.crt"
      SSLCertificateKeyFile "${SRVROOT}/conf/server.key"
    
      SSLVerifyClient none
      SSLVerifyDepth 10
    
      <Directory "d:/web/app/ssa/public">
        Options +Indexes +Includes +FollowSymLinks +MultiViews
        AllowOverride All
        Require local
      </Directory>
      
      #Redirect /wss /wss/
      #ProxyPass /wss/ ws://127.0.0.1:8090/
      #ProxyPassReverse /ws/ wss://127.0.0.1:8090/
    </VirtualHost>
    

    Please notice that for this virtual host I used the same certificate and key files I used for the Secure Websocket Server.

    Ok, that was it for my certificate issue.

    Now everything works as expected.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search