Receiving specific TCP commands with nodejs and handling them - node.js

I have a device in my local that sends JSON data through TCP:
ex. {"cmd": "listactions", "id": 13, "value": 100}
The data is send from 192.168.0.233 on port 8000
(I've checked this with wireshark)
I would like to (with my homeserver) intercept those specific commands with nodejs & send them through with pusher.
I have very little experience with nodejs & can't seem to get this working. I tried the following:
net = require('net');
var server = net.createServer(function(sock) {
sock.setEncoding('utf8');
sock.on('data', function (data) {
// post data to a server so it can be saved and stuff
console.log(data);
// close connection
sock.end();
});
sock.on('error', function (error) {
console.log('******* ERROR ' + error + ' *******');
// close connection
sock.end();
});
});
server.on('error', function (e) {
console.log(e);
});
server.listen(8000, '192.168.0.233', function(){
//success, listening
console.log('Server listening');
});
But it complaints about EADDRNOTAVAIL, from research I've learned that this means the port is in use... Which I don't understand because I'm able to with Wireshark.
What's the correct way to do this?

Wireshark doesn't listen on all ports. It uses a kernel driver (with libpcap or winpcap) to "sniff" data off the wire. That is, it doesn't sit in between anything. It's not a man-in-the-middle. It just receives a copy of data as it is sent along.
Your application needs to listen on that port if you expect it to receive data. You should use netstat to figure out what process is listening on port 8000 and kill it. Then, you can listen on port 8000.
You could in theory use libpcap to get your data but that's crazy. There is a ton of overhead, something has to listen on that port anyway (it's a TCP connection after all), and it's extremely complex to filter out what you want. Basically, you would be reimplementing the network stack. Don't.

Related

Node.js - Bi-directional communication between a tcp server and web portal

I've a GPS tracker device that sends data to my Node.js TCP server and I can send data back to device from the TCP server.
const net = require('net');
const port = 6565;
const host = '127.0.0.1';
const server = net.createServer(onClientConnection);
function onClientConnection(sock){
console.log(`${sock.remoteAddress}:${sock.remotePort} Connected`);
sock.on('data',function(data){
console.log(`${sock.remoteAddress}:${sock.remotePort} Says : ${data} `);
sock.write("Hello World!");
});
//Handle client connection termination.
sock.on('close',function(){
console.log(`${sock.remoteAddress}:${sock.remotePort} Terminated the connection`);
});
//Handle Client connection error.
sock.on('error',function(error){
console.error(`${sock.remoteAddress}:${sock.remotePort} Connection Error ${error}`);
});
};
server.listen(port,host,function(){
console.log(`Server started on port ${port} at ${host}`);
});
However I'm looking to extend this device/server interaction to a web portal from where I want to send/receive data from the device in real-time and I can't seem to wrap my head around how to approach this problem. Is it possible to do this? The device itself is a low-end device that don't seem to have a embedded web server. Can we create a REST API like interface between the web portal and TCP server to accomplish this task? I'm really lost. Any pointers?
Please help.

dgram node js client wait for server to come up

i need a udp client wait for udp server to be created to connect and send first message.
const dgram = require('dgram');
const client = dgram.createSocket('udp4');
client.connect(27015, 'localhost', function() {
client.send(message, (err) => {
});
});
this code works when the udp server is already running, but do nothing if I first start the client and then server. I need it to work in both cases.
UDP is a connection-less and an unreliable protocol, there is no way to know if the server is running or not on the client side.
See Difference between TCP and UDP?

Get webRTC to listen to a UDP connection

I have been really struggling to send data from Matlab over a network to a series of 'Dashboards' written in HTML/JS that essentially just display the data.
In Matlab I use uSend = udpport("datagram","IPV4","LocalHost","127.0.0.1","LocalPort",3333) then write(uSend,D,"char","LocalHost",2560) to send an array D=jsonencode([1,2,3,4,5]) to port 2560.
My current implementation uses NodeJS 'dgram' to receive the data. The implementation below works:
const dgram = require('dgram');
const socket = dgram.CreateSocket('udp4');
socket.on('message', (msg,rinfo) => {
console.log(`Data Received: ${JSON.parse(msg)}`)
})
socket.bind(2560,"127.0.0.1")
BUT: This only works with NodeJS i.e. run the script above node script.js. The 'Dashboards' need to run essentially on a chrome browser, which dgram won't work (not even with browserify, it's not a supported function).
Hence, my hands are sort of tied, with Matlab I can realistically only send UDP (it's multicast) and I can't get UDP data on the JS side of things.
I was wondering, with webRTC, is it possible to get it to listen to a port? e.g. something like webRTC listen to port 2560 #127.0.0.1?
Any help would be much appreciated! I am relatively new to programming so I may be asking the wrong question here. Thanks
WebRTC requires a lot more then just a UDP port unfortunately.
I would suggest instead running a node.js server that accepts incoming multicast traffic and caches like this.
const dgram = require('dgram');
const socket = dgram.CreateSocket('udp4');
let data = [];
socket.on('message', (msg,rinfo) => {
data.push(JSON.parse(msg))
})
socket.bind(2560,"127.0.0.1")
Then I would provide a HTTP endpoint that returns the JSON. You can have the browser poll this at an interval of your choosing.
const http = require('http');
const server = http.createServer((req, res) => {
response.end(JSON.stringify(data));
})
const port = 3000
server.listen(port, () => {
console.log(`Server listening on port ${port}`);
})
You can then test this by doing curl http://localhost:3000. You are just caching the data then making it available via HTTP request.
In the future I would look into using a Websocket instead. This way the server can push the data to the browser as soon as it is available. Using a HTTP endpoint requires the browser to request on an interval.

Server showing multiple client connection (net nodejs)

I am trying to make a server which listens on a internet facing port and forwards incoming http requests to an internal express server listening at another port. Following is the relevant part of the code I'm using.
var net = require('net');
var server = net.createServer();
server.listen(addr.from[3], addr.from[2], function(){
console.log('Server listening');
});
server.on('connection',function(from){
console.log('Client connected from '+ from.remoteAddress);
var to = net.createConnection({
host: addr.to[2],
port: addr.to[3]
});
from.pipe(to);
to.pipe(from);
from.on('error',function(err){
winston.error('Error at unix box'+err);
to.end();
});
to.on('error',function(err){
winston.error('Error at middleware server'+err);
from.end();
});
from.on('end',function(){
console.log('Client disconnected ');
to.end();
});
to.on('end',function(){
console.log('Middleware disconnected');
from.end();
});
});
The problem I'm encountering is that, when I open "ip:port" in the browser (which would be the internet facing port) I'm getting messages multiple "client connected from xxxxxx" msgs on the console. Can anyone help me understand why this is happening?
Whenever browser connects to a website it usually makes two requests: normal and to retrieve favicon.
Funny thing, is that the favicon request is not even displayed in browser developer tools.
To verify, you need to extract the request made, print it to server, and then observe why you get multiple requests. For that, connection might be too early, try hooking request event instead:
server.on('request', funtion(req, res) { console.log(req.url); });

NodeJS TCP Socket does not show client hostname information

lets say I've created a simple node.js TCP Socket server as follows.
var server = net.createServer(function (socket) {
socket.end("goodbye\n");
});
// listen on port 80, like a webserver would, and configured to accept connections to multiple hosts, ie test.example.com, sdfsdfsdf.example.com, example2.com.
server.listen(80, function() {
address = server.address();
console.log("opened server on %j", address);
});
server.on('connection', function(socket) {
//log('connection data', socket);
log('CONNECTED SOCKET DATA', socket.address());
log('CONNECTED LOCAL, %s:%s', socket.localAddress, socket.localPort);
log('CONNECTED %s:%s', socket.remoteAddress, socket.remotePort);
//How do I find the server hostname that the client connected to?
// eg test.example.com or example2.com
});
Once a tcp connection is made, I want to parse the hostname that the client attempted to connect to. However the socket does not seem to have this information.
The following is what I got when I ran the previous code (removed ip addresses)
CONNECTED SOCKET DATA { port: 80, family: 2, address: '[SERVER IP ADDRESS]' }
CONNECTED LOCAL, undefined:undefined
CONNECTED [CLIENT IP ADDRESS]:13263
I've gone through the nodejs socket documentation but I cant find anything related to host name. The documentation actually says that the socket.localAddress will be an IP Address, with makes it useless in my case.
That information is not available at the TCP layer. You need to look at the Host header at the HTTP layer when a request arrives. This will be available as req.headers.host when a request arrives. http://nodejs.org/docs/latest/api/all.html#all_message_headers
Also based on your comment, trying to run a non-HTTP server on port 80 is asking for trouble. You are going to get connections from web spiders and botnets all the time, so make sure your program properly handles HTTP clients connecting and disconnects them or perhaps sends an HTTP error message.
Joe is correct in the comment that if you are not using HTTP, your custom protocol will need to transmit the "virtual host" name from the client to the server in the first packet/header message of your custom protocol.

Resources