Allow WebSockets in Google Compute Engine (GCE) - node.js

I'm using Compute Engine (GCE) to run my socket server with Socket.IO (Node.js)
It's only working with polling. When I try to use a web client I receive this error code:
WebSocket connection to 'ws://myapp-socket.appspot.com/socket.io/?EIO=3&transport=websocket&sid=Tt4uNFR2fU82zsCIAADo' failed: Unexpected response code: 400
What am I doing wrong? Is it GCE configuration problem?

You cannot use the myapp-socket.appspot.com domain in your script when using WebSockets. Instead, you will need to use the external ip of the GCE instance and connect directly to that, opening any firewall ports you may be using.
I believe traffic going to the appspot.com domain is also going through frontend webservers and socket.io needs a direct connection to the server.

The Virtual Machines in Google Compute Engine have port 80 for http and port 443 for https. Using these ports for web-sockets solved the issue.

Related

HTTPS for socket.io via Cloudflare

I have a chrome extension which uses an externel socket.io server to connect clients together.
During development I was able to connect to the server via http://localhost:2087 just fine, but right now I need socket.io to work over HTTPS so I can access it from a browser tab being server by HTTPS.
I don't want to deal with certificates, and want to keep the code on the socket.io server mostly the same, so I want to proxy the IP for the server via Cloudflare and establish SSL like that.
But I haven't been able to, the socket.io server uses no other webserver, but I can change it to use the native NodeJS http or https libraries.
But I haven't been able to access the socket.io server via the Cloudflare proxy. Clouflare returns 522 errors, which means a connection timeout.
Apparantly flexible SSL only works with with ports 443->80
Other ports are not supported...

AWS Loadbalancer Proxy for Nodejs

I have configured the load balancer to route the request to two of Ec2 Instance running a NodeJs server. I need to direct the request coming from both http (port 80) and https (port 443) to http (port 80) of the EC2 instances in NodeJs. I have uploaded the ssl certificate to AWS and configured the load balancer to use ssl certificate. The problem is the request coming from http port doesn't automatically route to https. It has to be a server side script or snipped which I need to write in server.js which should be routing the http to https, i tried to do it and it run into endless redirection. So questions -
Is there any guide to do this from AWS ?
If not then how one can achieve this, any pointers or suggestions would be greatly appreciated.
On the server side you can check the X-Forwarded-Proto
(original request protocol) and if it's heaving value http you can send redirect (http 302) to a url with https protocol..
though with ALB (application load balancer you may specify a set of rules, maybe it's possible to do that there..)
I couldn't find a guide from AWS, but I will keep searching and update the answer in the case I find it.
Usually, when you write applications in Node.js, you specify which port should your app run at. It means that you will need two different servers listening. And when your app receives a request on port 80 (HTTP), it should redirect to your HTTPS server, like in this answer.
Another point that may be relevant to your question is that, in production environments, you don't usually bind a port to your Node.js server, since it's not production ready. You probably want to use a reverse proxy and load balancer like Nginx or HAProxy.
If you are using the AWS ALB (Application Load Balancer) they announced the http->https redirect today. Take a look: https://exampleloadbalancer.com/redirect_demo.html
Put your ELB behind the Cloudfront and in settings of your distribution select forward HTTP to HTTPS.
The following doc will be helpful
https://docs.aws.amazon.com/waf/latest/developerguide/tutorials-ddos-cross-service-ELB.html
This method has two benefit:
1-Your problem will be solve
2-You can use the benefit of the powerful CDN, for more information about Cloudfront read https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html
Update:
You can forward traffic from HTTP to HTTPS by edit your Listeners setting in your ELB.

Socket.IO keeps reconnecting Websocket on Cloudflare

I have a Node/Express app on server dedicated to sockets and on the client it's Angular 1.5. Running the code locally on http using the same architecture e.g. separate socket server it all works perfectly fine.
When I run the code locally it creates one connection and does very little polling via xhr. On cloudflare with https it does a lot of polling, reconnects continually and not all the messages seem to be getting to the web client
messages hit cloudflare which then redirects them to a loadbalancer running haproxy which then routes the requests to an app running in a docker instance on another machine.
Your Issue is most likely occuring beacause of an issue with cloudflare only allowing traffic to a limited set of ports. Try one of the ports listed in the below link for your server and try connecting to it.
https://support.cloudflare.com/hc/en-us/articles/200169156-Which-ports-will-Cloudflare-work-with-
After a lot of investigation I found the issue to be down to the config in haproxy. I needed to alter the timeouts around the socket routing.
This was nothing to do with ports not being open on cloudflare.
The following link helped me
http://blog.haproxy.com/2012/11/07/websockets-load-balancing-with-haproxy/

WebSocket over SSL: Cloudflare

I have a website behind cloudflare. I need to enable websockets over SSL without turning off cloudflare support. I have a PRO plan and hence won't get the new websocket support. I am using Nginx to proxy a SSL connection to a web socket running on a node server. Now, I read somewhere that cloudflare could work with approved ports would support websockets. Hence, I'm using 8443 for the Nginx port and another port for the node server. Using wscat it returns a 200 error.
$ wscat -c wss://xyz.com:8443
error: Error: unexpected server response (200)
I know that the websocket is expecting a 101 code. However, if I visit https://xyz.com:8443, I can see the page displayed by the node server telling me proxy is working. Also, once I turn off cloudflare support, the websocket starts working. Any clues to get this working. I know I can create a subdomain but I'd prefer running the websocket behind cloudflare.
If you're trying to access this through CloudFlare's network you'd need to explicitly have web sockets enabled on your domain before they will work -- regardless of the port. As in, even if the port can pass through our network, that won't automatically mean that web sockets will be enabled or accessible on your domain.
You can try contacting our support team to request an exception to see if they can enable it for your domain, but typically this is still only available at the business and enterprise levels.
Disclaimer: I work at CloudFlare.

Socket.io on port 80

I've made a node application which listens on port 80, my application works fine on localhost, but when I run it on my VPS, I get a different log and a different result ( websockets just don't work )
A comparison between localhost's log and VPS' log:
Node's log on localhost
Node's log on VPS
As you see, in VPS, xhr is used instead of websocket after it says "info: transport end (socket end)"
I don't use any web server on my VPS and I ran my application as root.
Are you running a web server in front of your node app on your VPS? If so, make sure it is new enough and properly configured to do websockets. For instance, on modern Ubuntu the stock nginx is not new enough yet to support web sockets, so you have to install a separate package to get websocket support.
2nd guess: is there a proxy server between your browser and your VPS?
Have you run it as the super user on the VPS? Normal users are typically blocked from opening ports below 1024.
Our server hosted on VPS, using port 80. The io connection fired through cellular data and through WIFI fine, but in some wifi networks it didn't.
So we had used different port, then it works.

Resources