How to establish SSL/TLS socket connection with NodeJS - node.js

I've created a very simple socket server with NodeJS (v8.11.3) and it's working fine. My goal is to keep a socket connection opened with an electronic device (IoT).
QUESTION: How to make communication secure, that is, how to make socket/SSL socket communication? NOTE: I have also created a self-signed certificate for testing.
The test socket server (without security) is the one below. I have no experience with NodeJS, so I think there are a lot better ways to establish a socket connection...
const net = require('net')
net.createServer(socket => {
socket.on('error', (err) => {
console.log('Socket Error: ')
console.log(err.stack)
})
socket.on('data', function(data){
msg = ''
msg = data.toString();
socket.write(msg)
console.log(msg)
})
}).listen(8001)

You can use the built-in tls module, which provides extensions of net.Server and net.Socket. As such, it works about the same as the net server creation, with more options and more events. There is a simple example in the tls.createServer section, which shows a basic server close to your code here.

Related

Socket.io client in NodeJS

I want to build a microservice infrastructure with nodejs services and a master service, the communication between these services should happen via socket.io, i've setup my socket.io server, but their browser client (socket.io-client) is not working in nodejs (i guess it uses some browser only APIs). Is there a way to create a nodejs socket.io (NOT WEBSOCKETS) client?
EDIT
My client side code:
import { io } from "socket.io-client";
const socket = io("127.0.0.1:3000");
socket.on("connect", () => {
console.log(socket.id);
});
socket.on("disconnect", () => {
console.log(socket.id);
});
My server side code:
import { Server } from "socket.io";
const io = new Server();
io.on("connection", (socket) => {
console.log(socket)
});
io.listen(3000);
Both are written in typescript, the package versions are:
socket.io: ^4.4.0
socket.io-client: ^4.4.0
The Problem is, that i don't get any logs in my console, so i think there is something wrong with client, because socket.io does not mention node in there client side compatiblity graph.
The problem is that you have to pass a valid URL here:
const socket = io("127.0.0.1:3000");
I have no idea why socket.io doesn't give you an error, but if you change that to:
const socket = io("http://127.0.0.1:3000");
Then, it will work.
If you set DEBUG=socket.io-client in your environment, it won't show you an error, but it will show you that it's trying to connect to:
undefined//127.0.0.1:3000
which would give you a clue, I guess.
If you set DEBUG=* in your environment, you will get a lot more debug info (so much that it's a bit hard to sort through).
Set Logging and Debugging Socket.io for more info.

Node: Connect angular 6 client to Node server

I have node TCP socket server that i implemented using net module as shown in below
const net = require("net");
const server = net.createServer();
server.on("connection", function (socket) {
socket.setEncoding('utf8');
socket.on("data", function (d) {
}
}
socket.on("end", function () {
clients.splice(clients.indexOf(socket), 1);
console.log('end event on socket fired');
});
and i want my angular 6 app as a client to this TCP server. So i explore on the internet i only get with socket.io. Basic scenario is i have two clients one is raspberry which communicate on TCP/IP to my server and one is angular app that communicate with server using http. Any idea how to achieve this?
As of my knowledge plain TCP/UDP connections from the browser is currently deprecated because of security issues. I believe you may have to use WebSockets both on angular and node sides.

How to use the net module from Node.js with browserify?

I want to use the net module from Node.js on the client side (in the browser):
var net = require('net');
So I looked up how to get Node.js modules to the client, and browserify seems to be the answer. I tried it with jQuery and it worked like a charm.
But for some reason the net module does not want to work. If I write require('jquery') it works fine, but if I write require('net') it does not work, meaning my bundled .js file is empty.
I tried to search for something else, but the only thing I found is net-browserify on Github. With this, at least my bundle.js file is filled, but I get a JavaScript error using this (it has something to do with the connect function).
This is my code which works on the server side just fine:
var net = require('net-browserify');
//or var net = require('net');
var client = new net.Socket();
client.connect({port:25003}, function() {
console.log('Connected');
client.write('Hello, server! Love, Client.');
});
client.on('data', function(data) {
console.log('Received: ' + data);
client.destroy(); // kill client after server's response
});
client.on('close', function() {
console.log('Connection closed');
});
I assume that net-browserify lets you use a specific connect function, but I don't know which.
How can I use the net module from Node.js on the client side?
This is because net gives you access to raw TCP sockets - which browsers simply cannot do from the JavaScript end. It is impossible for net to ever be ported to the client side until such an API is written (allowing arbitrary tcp traffic).
Your best bet if you want to send tcp data from the client to the server is using web sockets using the socket.io module or the ws one.
Your best bet if you want clients to communicate directly is to look into WebRTC

Leaking sockets (sockets.io)

I have a client that connects to a socket server (node.js). I seem to being leaking sockets.
Here is the flow that causes the leaked sockets.
Connect to socket server
Signout (I see the log out confirmation on the server)
Signin in again to the socket server (see confirmation on socket server)
Restart socket server quickly (force restart using supervisor module by resaving a file)
Client reconnects to socket server. I now see 2 sockets that have connected to the socket server, instead of what should be just one.
If I repeat steps 2-4, I can see multiple connections from the same client.
Here is my client socket.io code:
client.js:
function start_socket(tok){
console.log("socket trying to connect");
//try every second to reconnect
socket = io.connect(sockets_host, { query: $.param({token: tok}), 'forceNew' : true, 'reconnection limit' : 100, 'max reconnection attempts' : 'Infinity' });
socket.on('connect', function() {
console.log('connected to socket server');
set_loggedin_status('true');
});
socket.on('disconnect', function() {
console.log('disconnected from server');
set_loggedin_status('false');
close_socket(); //get leaked sockets, wether I call this or not, though less if I do...
});
socket.on('error',function(err){
console.log('socket error: ' + err);
attempt_login();
});
}
function close_socket(){
console.log("in close socket");
socket.disconnect(true);
set_loggedin_status('false');
}
I've tried the above without 'forceNew' : true,, but then I seem to have problems signing in again after the client signed-out.
If I call close_socket from within the disconnected event (and not just from elsewhere when the client chooses to signout), I seem to get fewer leaked sockets, but still get them.
How am I creating multiple sockets?
The solution, though not necessarily the answer to the question, was in my case to use socket.io.disconnect() instead of socket.disconnect().
However, this meant if the socket server goes down once i've already established a connection, that no reconnects were being tried. So, I have to handle this situation myself if using this approach to solve the leaking sockets.

NodeJS connect to wss on another server

There is a wss on another server that I'd like to connect to. Let's say its address is: wss://123.123.123.12:8843
I have a nodejs/expressjs app. How do I connect to it using socket.io? I know how to implement socket.io for a server/client setup, but how do I do it for two servers (one of which I don't have access to).
How do I setup my expressjs app to connect to the wss? Is there a way using socket.io or do I need to do it another way?
Socket.IO isn't a WebSocket. It is a transport system that supports WebSockets, but if you want to interface with other WebSockets, you'd have better luck using the ws module, which Socket.IO uses internally. This is how it's used:
var WebSocket = require('ws');
var ws = new WebSocket('ws://www.host.com/path');
ws.on('open', function() {
ws.send('something');
});
ws.on('message', function(data, flags) {
// flags.binary will be set if a binary data is received
// flags.masked will be set if the data was masked
});
If you actually just want to communicate with another Socket.IO server, then install the client on the server. It's used the same way as you would use with a browser client.
npm install socket.io-client
And then usage:
var socket = require('socket.io')('http://host/path');
socket.on('connect', function() {
socket.on('event', function(data) { });
socket.on('disconnect', function() { });
});

Resources