socket.io security - maybe allow only from specific domain? - node.js

I build a websocket (node.js + socket.io) service that will aggregate data on clients (resolution, clicks etc) and send to my admin (via websockets). However I have some concerns about security. On client's side my websocket server address is exposed like this:
var socket = new io.Socket('127.0.0.1', {'port': 3000});
so anyone can take that address and hit a milion requests (which will bring my server down).
How to protect my socket server? Maybe only allow socket connections from my domain (how)?

How to protect my socket server?
You can limit the number of concurrently connected clients. For example if there are 5000 actively connected clients through WebSockets, then new ones will be refused until there are some "free slots" for them.
Maybe only allow socket connections from my domain (how)?
Client (browser) connections doesn't have your domain as "origin".

Related

Persist websocket connection object across the multiple server

I am using a websocket library on server for establishing socket connection.
https://github.com/websockets/ws
I have a more than one server in cluster, I want to know how can I use same socket connection object on another server in cluster.
And also I want to know what is the best option for webchat implementation native websocket or socket.io
You cannot use the same actual socket object across multiple servers. The socket object represents a socket connection between a client and one physical server process. It is possible to build a virtual socket object that would know what server its connection is on, send that server a message to then send out over the actual socket from that other server.
The socket.io/redis adapter is one such virtual ways of doing this. You set up a node.js cluster and you use the redis adapter with socket.io. It uses a central redis-based store to keep track of which serve process each physical connection is one. Then, when you want to send a message to a particular client from any of the server processes, you send that message through socket.io and it looks up for you in the redis database where that socket is connected, contacts that actual server and asks it to send the message to that particular client over the socket.io connection that is currently present on that other server process. Similarly, you can broadcast to groups of sockets and it will do all the work under the covers of making sure the message gets to the clients no matter which actual server they are connected to.
You could surely build something similar yourself for plain webSocket connections and others have built pieces of it. I'm not familiar enough with what exists out there in the wild to offer any recommendations for a plain webSocket. There plenty of articles on scaling webSocket servers horizontally which you can find with Google and read to get started if you want to do it with a plain webSocket.

Difference in server port and websocket port in node.js chat application

I am trying to create a multi room chat application in node.js using socket.io and express. I am confused between use of server port and websocket port. I understand server port is used by the client to connect to server. But not sure about use of websocket port.
Thanks & Regards..
webSockets can share the same port as your web server and this is a common configuration. The reason this works is because of how a webSocket establishes a connection (all webSocket connections are initiated with an HTTP request). It works like this:
Client makes an HTTP request to a web server with a header specifying that they want to "upgrade" to the webSocket protocol and sends a security-related header.
Web server sees the upgrade request and, if it has support enabled for webSocket connections, it will respond with a 101 request (switching protocols) and another security related header.
Client gets the accepted upgrade and both ends switch to the webSocket protocol and the original TCP socket that started out using the HTTP protocol is now using the webSocket protocol.
In this manner, the same port and webServer can be used for regular HTTP requests or webSocket connection requests.
For a chat application it is common to use a webSocket connection because it is a continuous connection that more easily allows the server to send information directly to the client which is often needed in a chat application.
To understand more about how a webSocket connection and server work, see this reference on MDN: Writing WebSocket servers which shows the step by step process for initiating a webSocket connection.
Server socket is used by server... that keeps listening to coming sockets request in a loop... and websocket sends a request to server socket and bound a connection between two devices...
If you have / want to have web clients, WebSocket is going to be required, because there is no access to 'regular' TCP (or UDP) sockets from browser-based JavaScript (and I assume you do not want Flash, SilverLight or Java Applets, in 2017). WebSocket is not special because of the port number, but it is special because of the protocol: a WebSocket connection starts as a regular HTTP connection, and protocol upgrade reconfigures it afterwards, it is designed for the browser-world, and even capable of traversing HTTP proxies. After establishing the connection, it provides a full-duplex, bi-directional message stream, very usable for chat applications.
And because of being a Web-thing, you could simply use port 80, if you are allowed to.

Bypassing socket connections in node.js

I'm working in a project where we need to connect clients to devices behind LAN networks.
Brief description: there are "devices" connected, in a home for example, under a LAN created by a router. These devices create a full webserver, operating under linux, and using nodejs as the backend implementation language. They also have access to Internet, through the public IP of the router. On the other side, there are clients which can choose to which device to connect to.
The goal is to connect the clients with the webServer created by any device.
Up to now, my idea is to try to implement something similar to how TeamViewer works. As I understand, Teamviewer has a central server, which the agents connect to. When an agent connects to the central server, this one gets hold of the TCP connection, keeping it alive. When another client wants to access to the first client, the server bypasses both TCP connections. That way the server acts like a proxy, where it additionally routes the TCP connections. This also allows to connect to clients under LAN or firewalls (because the connections are created always from the clients).
If this is correct, what I would like to implement is a central server, in nodejs as well, which manages a pool of socket connections coming from the different active devices, and when a client wants to connect to one specific device, the server bypasses the incoming TCP connection of the client with the already existing connection of the device.
What I first would like to know is if this is possible in nodejs. My idea is to keep the device connections alive, so clients can inmediately connect to them, creating some sort of pool of device connections.
If implemented in C, I guess I could get hold of the socket descriptor, keeping it alive, and bypassing it to the incoming client request. But in nodejs I can't seem to find any modules that manage TCP connections.
Are there any high level npm packages which do this function? Else, is it possible to use lower level modules (like net) which have those functionalities.
Ideally I would like to implement it with high level modules (express), but if it's not possible, I could always rewrite the server using low level modules.
Thanks in advance

Horizontally scale socket.io with redis

I currently am creating a horizontally scalable socket.io server which looks like the following:
LoadBalancer (nginx)
Proxy1 Proxy2 Proxy3 Proxy{N}
BackEnd1 BackEnd2 BackEnd3 BackEnd4 BackEnd{N}
My question is, with socket-io redis module, can I send a message to a specific socket connected to one of the proxy servers from one of the backend servers if they are all connected to the same redis server? If so, how do I do that?
As you wan to scale socket.io server, and you have used nginx as load balancer, do not forget to setup sticky load balancing, othersie single connection will be connected to multiple server based on load balancer pass the connection to socket.io server. So better to use sticky load balancing
With the redis socket io adapter, you can send and receive message with one or more socket.io server with help of Redis Pub/Sub implementation.
if you tell me which technology is used for Proxy and Backend, i will let you know more information on this.
Using the socket.io-redis module all of your backend servers will share the same pool of connected users. You can emit from Backend1 and if a client is connected to Backend4 he will get the message.
The key for this working though with Socket.io is to use sticky sessions on nginx so that once I client connects, it stays on the same machine. This is because the way that socket.io starts with a WebSocket and several long polling threads, they all need to be on the same backend server to work correctly.
Instead of sticky sessions, you can change your client connection optons to use Websockets ONLY and this will remove the problems with the multiple connections to multiple servers as there will only be one connection, the single websocket. This will also make your app lose the ability to downgrade to long-polling instead of WebSockets.

Push notifications with websockets in a distributed Node.js app

I have a Node.js application deployed on multiple servers with Nginx server load-balancing the browser traffic to these servers. The server uses push notification mechanism (using websocket module) to communicate with the browser.
In the current setup, the browser loads an application page where it opens a client socket, which connects to the server. The websocket request is sent to Nginx, which sends it to one of the servers in the cluster. When an event happens on the server, it notifies the client browsers listening to the server websocket.
The problem is that each server is communicating only with a subset of the websocket clients. Also, each server is only aware of the events that take place on the server. As a result not all clients are notified of all the server events.
I can see several potential solutions:
Configure Nginx to send websocket requests from each browser to all the server in the cluster. I could not figure out how to do it. Load balancing does not support broadcasting.
Store websocket connections in the databse, so that all servers had access to it. I am not sure how to serialize the websocket connection object to store it in MongoDB.
Set up a communication mechanism among the servers in the cluster (some kind message bus) and whenever event happens, have all the servers notify the websocket clients they are tracking. This somewhat complicates the system and requires the nodes to know the addresses of each other. Which package is most suitable for such a solution?
What is the simplest way to implements distributed push notification in a Node.js app?

Resources