[galène] Couldn't connect to wss://…

[french below]

My YunoHost server

Hardware: Old laptop
YunoHost version: 11.2.10.3 (stable)
I have access to my server : Through SSH | through the webadmin | direct access via keyboard / screen
Are you in a special context or did you perform some particular tweaking on your YunoHost instance ? : no

Description of my issue

Hi ! I installed galène on our server, on its own subdomain, with the standard configuration. when I try to log in , a red error message pop up saying Couldn't connect to wss://[mysubdomain.mydomain.com]/ws there is nothing in galène’s logs, nor in nginx’s.

for some unknown reason, even if I redirect the port 1194 on the router and in yunohost firewall, yunohost’s diagnosis say that “Port 1194 is not reachable from the outside in IPv6.” I suppose my ISP (free) is blocking it somewhere. I tried to change the -turn port in galene.service to 1195, opened it on the server and redirect it on the router with the same result, blocked on IPV6.

I suppose it is the source of my issue but i’m not sure.


Description du problème

j’ai installé galène sur notre serveur, avec la configuration de base, sur son propre sous-domaine. quand j’essaie de me logger, j’ai une erreur disant simplement Couldn't connect to wss://[mysubdomain.mydomain.com]/ws, il n’y a pas d’erreur dans les logs de galène ou de nginx.

pour une raison obscure, même si le port 1194 est bien redirigé sur le routeur et ouvert dans le firewall du serveur, l’outil de diagnostic dit que le port n’est pas accessible depuis l’extèrieur en IPV6. Je suppose que mon fournisseur d’accès (free) le bloque quelque part. j’ai essayé d’utiliser le port 1195 (en changeant le port -turn dans galene.service, puis en ouvrant le port dans le firewall du serveur et en le redirigeant dans celui du routeur) avec le même résultat, le port n’est pas accessible en IPV6.

Je suppose que c’est la source du problème mais je ne suis pas sûr

Couldn’t connect to wss://[mysubdomain.mydomain.com]/ws

This indicates that the browser cannot reach the websocket. It’s surprising, since the websocket shares the port with the web server, so it should be reachable if the web server is reachable.

there is nothing in galène’s logs, nor in nginx’s.

Could you please check if there’s anything in the browser’s console? (Under Chromium and derived browsers, press Ctrl-j. Under Firefox, press Shift-Ctrl-k.)

Port 1194 is not reachable from the outside in IPv6.

That’s an unrelated issue, and it’s not concerning.

@jch thanks for your help… none of the keyboard shortcuts you gave are working for me, I’m not familiar with using the browser console, but here is what I found in firefox

NS_ERROR_CONTENT_BLOCKED: 
    connect https://visio.galetteaubeurre.ovh/protocol.js:292
    serverConnect https://visio.galetteaubeurre.ovh/galene.js:3900
    <anonymous> https://visio.galetteaubeurre.ovh/galene.js:3810
galene.js:3902:17
    serverConnect https://visio.galetteaubeurre.ovh/galene.js:3902
Content-Security-Policy: The page’s settings blocked the loading of a resource at wss://visio.galetteaubeurre.ovh/ws (“default-src”). protocol.js:292:17
NS_ERROR_CONTENT_BLOCKED: 
    connect https://visio.galetteaubeurre.ovh/protocol.js:292
    serverConnect https://visio.galetteaubeurre.ovh/galene.js:3900
    <anonymous> https://visio.galetteaubeurre.ovh/galene.js:3810
galene.js:3902:17
Content-Security-Policy: The page’s settings blocked the loading of a resource at wss://visio.galetteaubeurre.ovh/ws (“default-src”).

chromium is more verbose but I don’t know if it is really relevant (and copy-pasting is not easy) :

Refused to connect to 'wss://visio.galetteaubeurre.ovh/ws' because it violates the following Content Security Policy directive: "default-src https: data: blob:". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
isTrusted
: 
true
bubbles
: 
false
cancelBubble
: 
false
cancelable
: 
false
composed
: 
false
currentTarget
: 
WebSocket {url: 'wss://visio.galetteaubeurre.ovh/ws', readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
defaultPrevented
: 
false
eventPhase
: 
0
returnValue
: 
true
srcElement
: 
WebSocket {url: 'wss://visio.galetteaubeurre.ovh/ws', readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
target
: 
WebSocket {url: 'wss://visio.galetteaubeurre.ovh/ws', readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
timeStamp
: 
73179.89999997616
type
: 
"error"

and

Event {isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
isTrusted
: 
true
bubbles
: 
false
cancelBubble
: 
false
cancelable
: 
false
composed
: 
false
currentTarget
: 
WebSocket {url: 'wss://visio.galetteaubeurre.ovh/ws', readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
defaultPrevented
: 
false
eventPhase
: 
0
returnValue
: 
true
srcElement
: 
WebSocket {url: 'wss://visio.galetteaubeurre.ovh/ws', readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
target
: 
WebSocket {url: 'wss://visio.galetteaubeurre.ovh/ws', readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
timeStamp
: 
90859
type
: 
"error"
[[Prototype]]
: 
Event
AT_TARGET
: 
2
BUBBLING_PHASE
: 
3
CAPTURING_PHASE
: 
1
NONE
: 
0
bubbles
: 
(...)
cancelBubble
: 
(...)
cancelable
: 
(...)
composed
: 
(...)
composedPath
: 
ƒ composedPath()
currentTarget
: 
(...)
defaultPrevented
: 
(...)
eventPhase
: 
(...)
initEvent
: 
ƒ initEvent()
preventDefault
: 
ƒ preventDefault()
returnValue
: 
(...)
srcElement
: 
(...)
stopImmediatePropagation
: 
ƒ stopImmediatePropagation()
stopPropagation
: 
ƒ stopPropagation()
target
: 
(...)
timeStamp
: 
(...)
type
: 
(...)
constructor
: 
ƒ Event()
Symbol(Symbol.toStringTag)
: 
"Event"
get bubbles
: 
ƒ bubbles()
get cancelBubble
: 
ƒ cancelBubble()
set cancelBubble
: 
ƒ cancelBubble()
get cancelable
: 
ƒ cancelable()
get composed
: 
ƒ composed()
get currentTarget
: 
ƒ currentTarget()
get defaultPrevented
: 
ƒ defaultPrevented()
get eventPhase
: 
ƒ eventPhase()
get returnValue
: 
ƒ returnValue()
set returnValue
: 
ƒ returnValue()
get srcElement
: 
ƒ srcElement()
get target
: 
ƒ target()
get timeStamp
: 
ƒ timeStamp()
get type
: 
ƒ type()
[[Prototype]]
: 
Object
serverConnect	@	galene.js:3902
await in serverConnect (async)		
document.getElementById.onsubmit	@	galene.js:3810

as for my port 1194 issue, thanks for reassuring me !

Content-Security-Policy: The page’s settings blocked the loading of a resource at wss://visio.galetteaubeurre.ovh/ws (“default-src”). protocol.js:292:17
NS_ERROR_CONTENT_BLOCKED:

It looks like you’re running Galene behind a reverse proxy, and the reverse proxy rewriting the Content-Security-Policy (CSP) header. And the CSP header provided by the proxy is not correct for Galene.

Galene already provides a CSP header, which is lovingly customised for Galene’s needs. Please configure your reverse proxy to let through Galene’s CSP header unchanged.

(If you really insist, you could provide your own CSP header, in which case you need to ensure that it includes connect-src ws: wss: 'self', which is not the case in your site’s CSP header.)

I’ll try but I have no idea how to do so, though I suppose it has to do with nginx conf

any idea why my installing galene ends with this result ?

thanks anyway,
cheers.

I’m probably a bit tired but I fumbled with nginx conf files : I first tried to add the following line to galene.conf under location /auth/ { and location / { :

proxy_set_header  Content-Security-Policy "connect-src ws: wss: 'self'"; 

reloaded nginx, then restarted galene, ending up with the same issue.

then I tried editing security.conf.inc, adding connect-src ws: wss: 'self'; to the more_set_headers "Content-Security-Policy : […] line, restarted nginx and galene, [edit: it worked after I waited a few minutes, but I’m pretty sure that editing a file named “security” without fully understanding what I enabled exactly is not a good idea…]

I still don’t understand why I’d have a reverse proxy configured as this is the only computer accessible from the outside on our local network, and a pretty simple yunohost installation (with several applications and subdomains, though), and I don’t understand where this CSP would be configured elsewhere…

I think I found how to change the CSP only for galene by adding the following line to galene.conf under location /auth/ { and location / { :

add_header  Content-Security-Policy "connect-src ws: wss: 'self'";

I’d like a confirmation that it is not a big mistake before saying out loud that my problem is fixed (and also why I need to do that)

[edit: I must have messed up with the restarting of nginx because it doesn’t work anymore.]

Nginx shouldn’t be modifying the header in the first place, it should just pass through Galene’s header. So there’s clearly something wrong, perhaps a local configuration or a different package that causes nginx to corrupt Galene’s headers.

@ericg @tituspijean Any ideas?

@jch thanks for your help… the only workaround I found is editing security.conf.inc (I’m still not comfortable with that).

I still don’t understand why this issue occurred and I would love to know if my workaround is “just a bit dirty” or “badbadbad”…