Webpage script connecting to two-way SSL fails - javascript

I am running a website server and a websocket server on two different ports. I'd like two-way SSL enabled on both. The website is using a gunicorn/flask app and is working fine for the two-way SSL on all browsers (desktop/mobile, except mobile Firefox). Inside that webpage is a script to connect to the websocket (python websockets server) which also has two-way SSL enabled.
This only works in desktop Firefox; anything else gives the error WebSocket connection to '<domain>:<port>' failed: WebSocket opening handshake was canceled.
On desktop Firefox, it requests user certificates for both the webpage and websocket, but like I said anything else returns the above error.
I've been scouring the internet for solutions to this and have seen some info on using proxies with certain hosting providers but I am hosting these myself and would rather not get too deep in setting up further stuff, if possible. For clarification, turning off two-way ssl and only doing server cert verification does work. It is only when the websocket asks for the clients cert that nothing happens and the error is in the console (client side, nothing shows on the server side).
Does anyone have ideas on how to keep two-way SSL for the site and websocket? Security is a major concern for this application.

This looks like the same problem as described in Cannot create WSS connection with Chrome, other browser work. The problem is that Chrome and Safari will not prompt for a client certificate for a Websockets connection. See this bug from 2013 which is still open.
If the user made already a choice which client certificate to use on the same origin it will work though. Only, an origin includes the port and your Websocket is on a different port than your website. This kind of setup can also cause other problems (like with restrictive firewalls) so it is a good idea to use a single origin and reverse proxy the Websocket from this origin. See this comment on the same bug on how to do this with nginx.

Related

How to stop chrome from upgrading websockets from WS to WSS when the websocket object is created on an HTTPS page

I made a real browser port of minecraft here that is multiplayer only, it is based on websockets.
https://g.eags.us/eaglercraft/
I want the game on this page to be able to connect to servers using both the WS and WSS websocket protocol, so buying web SSL certificates is not mandatory for the people who are just trying to set up small private servers to use to play this game on from school computers or something. Both my origin server and cloudflare are currently configured to be strictly HTTPS only and you cannot normally initialize an insecure WS websocket from a secure HTTPS page, meaning anyone trying to play the game on their own server off of my 'official' link will need an SSL certificate and a WSS URI.
I have added the content-security-policy: upgrade-insecure-requests header to the link I posted above. I am under the impression that this enables regular insecure HTTP/WS connections to be made on the page even if the page was loaded via HTTPS but it doesn't appear to work. When I create a WebSocket object in chrome devtools console of this page and tried connecting it to a WS URI, the network tab shows that the actual request used by the object had the WS in the URI replaced with WSS even though the URI I typed was WS.
How do I disable all this behavior for this specific page and just perform the websocket request as-is
I misinterpreted the header's behavior. It was working as advertised, upgrading the URI from WS to WSS. I initially interpreted it as a header that applies a permission override for the browser to just treat all socket URIs as if they had already been upgraded to WSS without actually upgrading the underlying URIs and requests.
Apologies for my 3:00 AM confusion, see the MDN Page for more clarification

Websockets not working on at least one machine

I have an application that uses websockets.
Web server is glassfish 4.1.1 and we are using #ServerEndpoint for the websockets implementation on a server side.
In all computers everything worked fine up to the date, when on one laptop of some customer we got an error (he uses Google Chrome):
failed to execute 'send' on websocket: Still in CONNECTING state
At that computer this error appears permanently, blocking every functionality that concerns websockets.
We do not setup specific port for websockets. So I assume they are using default one - 80. Other pages loaded successfully (so, our website is accessible from that laptop).
Do you have any key of where to dig? Why only one laptop fails?
Is it needed to provide more information?
Thank you in advance!
Could be many things:
Firewall
Anti-virus
Chrome flag (like running: chrome.exe --disable-web-sockets)
Virus/malware
Man-in-the-middle (MitM)
I suggest to install Firefox. If Firefox has no issues there, then Chrome surely has issues.
I had the same problem. Check what is the port that you try to connect from frontend app (your socket has to be asigned to a port). My WS server was listening on PORT 8080 and some users had outgoing port blocked. I made a proxy from 80 to 8080 and now all users have access.

WebSocket errors when using TLS (but not without)

I have a web application that uses WebSockets to communicate between browser and server. When serving as ws, everything works as intended. If I change the protocol to wss, things mostly work as expected (the majority of messages passed from client to server, or vice versa, are received), but I occasionally one of the following errors in the Chrome console:
"Could not decode a text frame as UTF-8."
or
"Invalid frame header"
...at which point Chrome releases the connection.
I have observed this both when serving wss directly from the server (runs on .NET, uses SuperWebSocket), and in a configuration where the server uses ws and Apache's mod_proxy_wstunnel to reverse proxy to this using the wss protocol. I have also set up a simple "echo" server under the same Apache configuration, and don't observe the issue; this leads me to believe there's something funny about the data we're passing to the SuperWebSocket API. (The messages which cause the error are valid UTF-8, and again, don't see this issue when serving over ws.)
I'm at a loss for how a protocol change would cause such an issue to occur, which leads me to my question:
Are there cases where a WebSocket frame might be valid when sent without TLS but would become corrupted when sent with TLS?
Are there cases where a WebSocket frame might be valid when sent without TLS but would become corrupted when sent with TLS?
No, wss:// is the same as ws:// only that it is not using plain TCP but TCP+TLS. The WebSockets protocol itself is not aware if it is running inside a plain TCP connection or a TLS protected TCP connection. This is similar to https:// vs. http://.
But a TLS connection is more sensible to data corruption. That is if some man in the middle modifies the packets properly simple ws:// will not notice while wss:// will croak because the modification of the packet was detected. But you should get the error then at the connection level (i.e. connection broke or similar) and not at the WebSockets level like in your case (invalid frame header).
I have no idea what you are running as a WebSockets backend but I would suggest that the problem lies there. Because of the additional TLS layer wss:// might behave slightly different regarding timing and buffering of data inside the server so there might be a race conditions which happens more likely when wss:// is in use compared to ws://.

Cross browser support for Websockets in ActiveMQ

It seems clear that Apollo has support for CORS in their websockets protocol, but I can find nothing comparable in ActiveMQ. In Apollo you can add the parameter "cors_origin" to the connector description, but I can find nothing comparable in ActiveMQ's documentation. I've tried the Apollo parameter but I'm still getting connection refused errors.
I'm attempting to use the Paho Mqtt javascript client to connect. The Go clients I've written work fine over both tcp and websockets, but I've had no luck getting the js client to work.
I'm pretty sure the problem is CORS. Any ideas on how to configure ActiveMQ?
My problem with the refused connections had nothing to do with CORS. It was an authentication problem with the ActiveMQ broker (my bug, now fixed).
However, it is interesting to node that ActiveMQ appears to completely ignore the websockets "Origin" header from the browser. In other words, it will accept connections from any host (including localhost). Apollo appears to behave differently with specific CORS configuration.

Chrome & Safari revert to xhr-polling rather than websockets with socket.io

I have a problem with websockets and socket.io. When I try to connect to my node server with socket.io it initially connects using websockets but when reverts to jsonp-polling shortly after.
This is the output from the node sever when I connect:
8 Jun 07:01:15 - Initializing client with transport "websocket"
8 Jun 07:01:19 - Initializing client with transport "jsonp-polling"
8 Jun 07:01:19 - Client 16630339180119336 connected
This happens in Chrome & Safari.
I have updated to the latest socket.io version 0.6.17 and am running node 0.4.7.
I have tried deleteing my cookies and cache as suggested on github and SO, however the problem remains. Also, when I try to force websockets it never fully connects with a session ID.
Does anyone have any ideas?
Websocket API is not supported by default in all the browsers at the moment (as per my knowledge) it should work on chromium though try testing it on chromium or firefox(after editing the default settings)and see if that still reverts to XHRPolling.
I am running it on a different IP as I need to run node on port 80 which causes conflict on my web server with Apache. Can websockets/flashsockets not be use cross-domain?
Now there might be 2 different reasons for the bug from here
Web/Flash Sockets will not let u connect to the node.js client unless either u specify a differnt port like 81 or u specially specify apache to proxy the incoming request to Node.
an easy solution could be writing the Node.js based HTTP server to just relay data from Apache (and setting Apache to run on a differnt port then 80)
This link tells how to do that... in this process you can make Node.js do something like check if the request is from a websocket/httpbrowser if thats an http browser forward the request to Apache if not ie if thats from web/flash sockets then handle the socket accordingly. or as commented on the question. Specify APACHE to proxy to Node.js.
Flashsockets require you to serve a crossdomain policy file on port 843 are you sure you are providing a cross domain file? (I think socket.io has inbuilt functionality to do that but still its always good to check.)
As told on the socket.io main website
In order to provide realtime connectivity on every browser, Socket.IO selects the most capable transport at runtime, without it affecting the API.
WebSocket
Adobe® Flash® Socket
AJAX long polling
AJAX multipart streaming
Forever Iframe
JSONP Polling
It's pretty clear that it will revert to AJAX Long Polling if websockets are disabled and Adobe Flash Socket fails to connect (this might be due to the unavailability of the policy file).
Here's a sample code for the cross domain file which you can include in your code and see if that makes your server run with websockets.
var net = require("net");
// Node.js
var Policy = net.createServer(function(socket)
{
socket.setEncoding('utf8');
socket.on('connect',function(){
console.log("Policy Request");
socket.end("<?xml version=\"1.0\"?><!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" secure=\"false\"/></cross-domain-policy>");
});
});
Policy.listen(843);

Categories