Mattermost, Inc.

WebRTC ERR_SSL_PROTOCOL_ERROR

Summary

I am unable to get WebRTC to work.

Steps to reproduce

I used the instructions provided here: https://docs.mattermost.com/deployment/webrtc.html

Observed behavior

I am getting the following error:
There was an error connecting your video call
I am getting the follwing console error:
WebSocket connection to 'wss://[IP_ADDRESS]:8189/' failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR

We are using self signed certificates for the Mattermost server and currently using the certificate provided with Janus in the docker container. (assuming that the crt in the /opt/janus/certs location is correct.

janus.transport.websockets.cfg

; WebSockets stuff: whether they should be enabled, which ports they
; should use, and so on.
[general]
json = compact                          ; Whether the JSON messages should be indented (default),
                                                        ; plain (no indentation) or compact (no indentation and no spaces)
ws = yes                                        ; Whether to enable the WebSockets API
ws_port = 8188                          ; WebSockets server port
;ws_interface = eth0            ; Whether we should bind this server to a specific interface only
;ws_ip = 192.168.0.1            ; Whether we should bind this server to a specific IP address only
wss = yes                                       ; Whether to enable secure WebSockets
wss_port = 8189;                        ; WebSockets server secure port, if enabled
;wss_interface = eth0           ; Whether we should bind this server to a specific interface only
;wss_ip = 192.168.0.1           ; Whether we should bind this server to a specific IP address only
;ws_logging = 7                         ; libwebsockets debugging level (0 by default)
;ws_acl = 127.,192.168.0.       ; Only allow requests coming from this comma separated list of addresses

; If you want to expose the Admin API via WebSockets as well, you need to
; specify a different server instance, as you cannot mix Janus API and
; Admin API messaging. Notice that by default the Admin API support via
; WebSockets is disabled.
[admin]
admin_ws = no                                   ; Whether to enable the Admin API WebSockets API
admin_ws_port = 7188                    ; Admin API WebSockets server port, if enabled
;admin_ws_interface = eth0              ; Whether we should bind this server to a specific interface only
;admin_ws_ip = 192.168.0.1              ; Whether we should bind this server to a specific IP address only
admin_wss = yes                                 ; Whether to enable the Admin API secure WebSockets
;admin_wss_port = 7989                  ; Admin API WebSockets server secure port, if enabled
;admin_wss_interface = eth0             ; Whether we should bind this server to a specific interface only
;admin_wss_ip = 192.168.0.1             ; Whether we should bind this server to a specific IP address only
;admin_ws_acl = 127.,192.168.0. ; Only allow requests coming from this comma separated list of addresses

; Certificate and key to use for any secure WebSocket server, if needed.
[certificates]
cert_pem = /opt/janus/certs/certificate.crt
cert_key = /opt/janus/certs/privateKey.key

janus.transport.http.cfg

; Web server stuff: whether any should be enabled, which ports they
; should use, whether security should be handled directly or demanded to
; an external application (e.g., web frontend) and what should be the
; base path for the Janus API protocol. You can also specify the
; threading model to use for the HTTP webserver: by default this is
; 'unlimited' (which means a thread per connection, as specified by the
; libmicrohttpd documentation), using a number will make use of a thread
; pool instead. Since long polls are involved, make sure you choose a
; value that doesn't keep new connections waiting.
[general]
json = compact                          ; Whether the JSON messages should be indented (default),
                                                        ; plain (no indentation) or compact (no indentation and no spaces)
base_path = /janus                      ; Base path to bind to in the web server (plain HTTP only)
threads = unlimited                     ; unlimited=thread per connection, number=thread pool
http = yes                                      ; Whether to enable the plain HTTP interface
port = 8088                                     ; Web server HTTP port
;interface = eth0                       ; Whether we should bind this server to a specific interface only
;ip = 192.168.0.1                       ; Whether we should bind this server to a specific IP address (v4 or v6) only
https = yes                                     ; Whether to enable HTTPS (default=no)
secure_port = 8089                      ; Web server HTTPS port, if enabled
;secure_interface = eth0        ; Whether we should bind this server to a specific interface only
;secure_ip = 192.168.0.1        ; Whether we should bind this server to a specific IP address (v4 or v6) only
;acl = 127.,192.168.0.          ; Only allow requests coming from this comma separated list of addresses

; Janus can also expose an admin/monitor endpoint, to allow you to check
; which sessions are up, which handles they're managing, their current
; status and so on. This provides a useful aid when debugging potential
; issues in Janus. The configuration is pretty much the same as the one
; already presented above for the webserver stuff, as the API is very
; similar: choose the base bath for the admin/monitor endpoint (/admin
; by default), ports, threading model, etc. Besides, you can specify
; a secret that must be provided in all requests as a crude form of
; authorization mechanism, and partial or full source IPs if you want to
; limit access basing on IP addresses. For security reasons, this
; endpoint is disabled by default, enable it by setting admin_http=yes.
[admin]
admin_base_path = /admin                ; Base path to bind to in the admin/monitor web server (plain HTTP only)
admin_threads = unlimited               ; unlimited=thread per connection, number=thread pool
admin_http = yes                                        ; Whether to enable the plain HTTP interface
admin_port = 7088                               ; Admin/monitor web server HTTP port
;admin_interface = eth0                 ; Whether we should bind this server to a specific interface only
;admin_ip = 192.168.0.1                 ; Whether we should bind this server to a specific IP address (v4 or v6) only
admin_https = yes                               ; Whether to enable HTTPS (default=no)
admin_secure_port = 7089                ; Admin/monitor web server HTTPS port, if enabled
;admin_secure_interface = eth0  ; Whether we should bind this server to a specific interface only
;admin_secure_ip = 192.168.0.1  ; Whether we should bind this server to a specific IP address (v4 or v6) only
;admin_acl = 127.,192.168.0.    ; Only allow requests coming from this comma separated list of addresses


; Certificate and key to use for HTTPS.
[certificates]
cert_pem = /opt/janus/certs/certificate.crt
cert_key = /opt/janus/certs/privateKey.key

Mattermost WebRTC System Console Config

Gateway WebSocket URL:
wss://[IP_ADDRESS]:8189

Gateway Admin URL:
https://[IP_ADDRESS]:7089/admin

Gateway Admin Secret:
janusoverlord

I know I should change the default password. I will do that once I can prove this thing will work.

https://[IP_ADDERESS]:7089/admin/info is accessible - though giving a certificate error. Once I ‘accept the risk’ I get the response.

So, I’ve copied over the cert and privkey pem’s to Janus and updated the reference to those files in janus.cfg , janus.transport.http.config and janus.transport.websockets.cfg
Now when I access the https://[IP_ADDRESS]:7089/admin/info location I do not receive the certificate error.

The WebSocket connection to 'wss://[IP_ADDRESS]:8189/' failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR is still present, but only on the first instance of trying to make the call. If I close the call window and try again the error is repeated. Previously, the error would be received with every call.

do you have Enable Insecure Outgoing Connections set to true in the Admin Console -> Security -> Connections tab?

Forgot to mention that…but Yes I do.

[EDIT]
When I have it (Enable Insecure Outgoing Connections) set to false I get the following error:
GET https://[IP_ADDRESS]:8066/api/v4/webrtc/token 500 ()

So I’ve been doing more troubleshooting and am not getting anywhere…

I did see this in the initial start logs of the docker container though:
NOTICE: SSL disabled: no LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT

I have a feeling that has something to do with it.

So I think I’ve made a little more head way.
I edited the /janus-gateway/transports/janus_websockets.c file
Line 519 info.options = 0
I change it to info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;

I run make install in/janus-gateway` and then restart the container

The warning is not there in the secure section…

And when I make a call, most of the times it will connect and after about 5-10 seconds will disconnect. On both ends the chat window comes up and either side can see their video feed.

Sometimes the call will stay connected but neither side can see the other. Either side can click the mute or stop video buttons and that is seen on the opposing side of the call.

The following is what I see in logs

Creating new handle in session 6181021750456722: 8384222687455928
Creating new handle in session 3803131647124302: 518856034359449
[8384222687455928] Creating ICE agent (ICE Full mode, controlled)
[518856034359449] Creating ICE agent (ICE Full mode, controlling)
[WARN] [518856034359449] ICE failed for component 1 in stream 1, but we're still waiting for some info so we don't care... (trickle pending, answer received, alert not set)
[ERR] [ice.c:janus_ice_cb_component_state_changed:1511] [8384222687455928] ICE failed for component 1 in stream 1...
No WebRTC media anymore
Detaching handle from JANUS VideoCall plugin
No WebRTC media anymore
[ERR] [ice.c:janus_plugin_session_is_alive:385] Invalid plugin session (0x7f5554005e00)
[WARN] No call to hangup
Detaching handle from JANUS VideoCall plugin
No WebRTC media anymore
Cleaning up handle 518856034359449...
[518856034359449] WebRTC resources freed
[518856034359449] Handle and related resources freed
Cleaning up handle 8384222687455928...
[8384222687455928] WebRTC resources freed
[8384222687455928] Handle and related resources freed

A Firefox to Firefox call is not successful at all. Both sides have authorized access to the Mic/Video.

Chrome to Chrome connects.
When a call connects and does not automatically hangup, I see this in the logs:

Creating new session: 2420353952547583
Creating new handle in session 2420353952547583: 8951761033967620
Creating new session: 2461625710341841
Creating new handle in session 2461625710341841: 2954164223073112
[8951761033967620] Creating ICE agent (ICE Full mode, controlled)
[2954164223073112] Creating ICE agent (ICE Full mode, controlling)
[WARN] [8951761033967620] ICE failed for component 1 in stream 1, but we're still waiting for some info so we don't care... (trickle pending, answer received, alert not set)
[WARN] [2954164223073112]     Missing valid SRTP session (packet arrived too early?), skipping...
[2954164223073112] The DTLS handshake has been completed
WebRTC media is now available
[WARN] [8951761033967620] ICE failed for component 1 in stream 1, but we're still waiting for some info so we don't care... (trickle pending, answer received, alert not set)

At this point and after all your findings I think the best place to ask would be in the janus repo, I’m really sorry I can’t be of much help here