how to connect via WebSocket running on Ubuntu server - node.js

Im have hetzner server on which im trying to run WebSocket. Unfortunately I got stack so here is my code from test.js)
const https = require('https');
const fs = require('fs');
const ws = require('ws');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
};
let server = http.createServer(options, (req, res) => {
console.log(req);
res.writeHead(200);
res.end();
});
server.addListener('upgrade', (req, res, head) => console.log('UPGRADE:', req.url));
server.on('error', (err) => console.error(err));
server.listen(8080, () => console.log('started on 8080'));
const wss = new ws.Server({ server, path: '/echo' });
wss.on('connection', (ws) => {
console.log('client connected');
ws.send('Hello');
ws.on('message', (data) => ws.send('Receive: ' + data));
});
wss.on('error', (e) => console.log(e));
* I got this code from some sources
After running the server I got message in console started on 8080. Nothing else... I tried to test it but I always got errors with no code. It looks like service where I tested it cannot find WebSocket. It is possible that problem actually in connecting to the serer.
Im not shure which path string should I use. I have hostname ubuntu-s**** and server IP 49.****. I did lots of attempts with 'wss://ubuntu-s***:8080/echo' and 'wss://49.***:8080/echo' but none of them gave any result
I still have no messages in console that cliend tried to connect :( Moreover I tried to run it on the local server (of course I removed SSL sertificates connecthion and changed server protocol to HTTP) and it works perfectly!!!
Thanks a lot for urs replies
UPD: message I got when trying to connect ws WebSocket connection to 'ws://49.***:8080/echo' failed:

First double check if the IP address is correct then change protocol to HTTP because you are using it on top of HTTP:
http://49.***:8080/echo

Related

I need to secure my node js website to HTTPS running on the default 80 port of HTTP

I am running my server on ionos hosting and executing nodejs on the default port of 80.
I don't know how to enable the HTTPS for it.
Following is my sample node js server creation code:
const Https = require('https');
const fs = require('fs');
const httpsServer = Https.createServer({
key: fs.readFileSync("private.key"),
cert: fs.readFileSync("Dev-2020-09-12-013930.cer")
}, app);
var io = require('socket.io').listen(Https);
global.SOCKET = io;
const ip = require('ip');
console.log('websocket server start.' + ' ipaddress = ' + ip.address() );
// const socket = io('http://localhost:5000');
httpsServer.listen(80, function () {
console.log('Server port: ' + port);
});
I have generated certificates and added them. On running the server it gives message of server started but does not load on browser.
Try adding these lines of code and see if you get "Hello" text in your browser.
https.get("/", (req, res) => {
res.send("Hello");
});
if that didn't work try doing it this way
httpsServer.get("/", (req, res) => {
res.send("Hello");
});
EDIT
Check out the official documentation https://nodejs.org/api/https.html

Why does my websocket handshake fail with unexpected response 200?

I have seen this question several times, but I feel that my use case is not quite addressed, so I'm posting it below:
I get this error when trying to connect to my websocket:
scripts.js:44 WebSocket connection to 'ws://localhost:3000/' failed: Error during WebSocket handshake: Unexpected response code: 200
There's one small change that makes it fail versus succeed. See below:
Server.js:
'use strict';
const express = require('express');
const WebSocket = require('ws');
const PORT = process.env.PORT || 3000;
// Failing:
const server = express().use(express.static('public'));
server.get('/', function (req, res) {
res.sendFile(path.join(__dirname + '/public/index.html'));
});
server.listen(PORT, () => {
console.log(`Example app listening on PORT ${PORT}!`)
});
///
// Working (no websocket connection issues):
///const server = express().use(express.static('public'))
// .listen(PORT, () => {
// console.log(`Example app listening on PORT ${PORT}!`)
// });
const wss = new WebSocket.Server({ server });
wss.on('connection', function connection(ws) {
console.log(ws);
ws.on('message', function incoming(message) {
console.log('received message: %s', message);
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});
relevant: client code:
var HOST = location.origin.replace(/^http/, 'ws');
var socket = new WebSocket(HOST); //this is the line where the connection is attempted.
Running on localhost, ngrok, or deployed to heroku seems to make no difference, unless I missed something...
I have tried various things from other posts but to no avail. They mention changing networking configurations (doesn't seem relevant to my use), or various ways to configuring express js, but they don't help. It's really just that small change in the above code. Is the websocket hitting the GET route?

Can't get WebSocket Server running on a subdomain (Plesk, Linux, NodeJs, Express)

I’ve developed myself a little WebSocket Server which works perfectly (local - on my IDE). The problem is that I want to host it on my server managed with Plesk under a specific subdomain that I've created: ws.my-url.de.
This is my server.js file:
const {logInfo} = require('./logger');
const WebSocketServer = require('ws').Server;
const express = require('express');
const uuid = require('node-uuid');
const app = express();
const wss = new WebSocketServer({
server: app.listen(process.env.PORT || 8888)
});
logInfo('WebSocket Server successfully started');
wss.on('connection', ws => {
ws.id = uuid.v4();
logInfo(`Client connected: ${ws.id}`);
ws.on('message', function () {
logInfo(`New message from client: ${ws.id}`);
});
ws.on('close', function () {
logInfo(`Client: ${ws.id} closed connection`);
});
});
wss.on('close', function () {
logInfo('WebSocket Server stopped');
});
app.post('/', function (req, res) {
logInfo(req);
});
I've also implemented a logger that logs out to a file which works also great (directly on start e.g. my startup message) but inside the logs folder on my server is a yawning emptiness.
I really can't get my WebSocket Server running on my server. To leave no stone unturned, I've disabled the proxy mode from nginx but after trying to connect to wss://ws.my-url.de I'm getting this error:
WebSocket connection to 'wss://ws.my-url.de/' failed: Error during WebSocket handshake: Unexpected response code: 500
So I can say that my server is not starting. To be really sure (and to exclude other things), I've wrote a little http server found in the internet and this ran straight out of the box after pressing the Restart App button (I saw the response in the browser window):
const http = require('http');
http.createServer(function(request, response) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('App is running…');
}).listen(process.env.PORT);
This is my configuration by the way:
When I open the URL after trying to start my WebSocket Server, I'm getting this error:
So what I'm doing wrong here? I don't want a page I can open, I just want to get this running as a little service which is accessible over my subdomain. I'm very overwhelmed with this and thankful for every person who can help me.

Can't get Hello World with Node.js in Cloud9

I can't figure out how to get my server to respond with Hello World.
I don't even know what IP address is. Is the ip listed on the tab of my terminal it?
I just created an EC2 environment with the default Node.js template.
Do I need to setup more things beforehand?
https://i.stack.imgur.com/4m85x.png
Try the solution bellow and let me know if you need any explanation:
const http = require("http");
const port = 3000; // make sure the port number is not used
const requestHandler = (req, res) => {
req.on('Error occurerd', (err) => {
console.error(err);
res.end();
});
res.end("Hello from AWS Cloud9!");
}
const server = http.createServer(requestHandler);
server.listen(port, () => {
console.log(`Server is listening on port ${port}!`);
// Run your script then copy past this url in your browser 127.0.0.1:3000
});

Socket.IO server.origins always returns '*' as the origin value (Nodejs)

I am trying to build a two way socket.io server/client connection. The server will remain behind one IP/domain and the client will behind a different IP. The point is to notify me when the server goes offline, in case of power outage or server failure. The issue I am having, is I am trying to secure the socket so not just anyone can connect to the socket. Socket.IO has a server.origins function that will return the origin of socket trying to connect. Their API documentation explains it like this.
io.origins((origin, callback) => {
if (origin !== 'https://foo.example.com') {
return callback('origin not allowed', false);
}
callback(null, true);
});
The issue I am having is whenever I connect to the socket.io server with socket.io-client the origin is always '*'.
Under potential drawbacks in there API is says:
"in some situations, when it is not possible to determine origin it may have value of *"
How do I get socket.io it see the IP where the socket connection request is coming from?
Once the connection is established I can use the socket information and see the IP where the socket lives, but the connection is already made. I am trying to stop rouge connections.
# Server
const express = require('express');
const app = express();
const chalk = require('chalk')
const server = require('http').createServer(app);
const io = require('socket.io')(server);
const cors = require('cors');
const port = 4424;
app.use(cors());
io.origins((origin, callback) => {
console.log(origin);
if (origin !== '*') {
return callback('origin not allowed', false);
}
callback(null, true);
});
io.on('connection', (socket) => {
console.log('Client connected...');
socket.on('join', (data) => {
console.log(data);
socket.emit('messages', 'Hello from server');
});
})
server.listen(port, () => console.log(chalk.blue(`Express started on port ${port}!`)));
Client:
# Client
const io = require('socket.io-client');
const socket = io('https://"MY DOMAIN THAT THE SERVER IS BEHIND"', { reconnect: true })
socket.on('connect', (data) => {
console.log("Connection successful");
socket.emit('join', 'Hello World from client');
});
socket.on('connect_error', (error) => {
console.log("Connection error");
});
socket.on('disconnect', (timeout) => {
console.log("Connection disconnected");
})
socket.on('messages', (data) => {
console.log(data);
});
I have the server behind a NGINX server using SSL, and connected to the server with the client on a different IP and it goes through and creates the connection, but the Origin is always "*".
Actually I found out you can use middleware with Socket.io with the io.use() function. I just wrote a simple middleware that checks the incoming socket ip with a list of approved ips.
io.use((socket, next) => {
const ip = socket.handshake.headers['x-forwarded-for']
if (firewall(ip))
{
return next();
}
})
And firewall is a function that checks if the ip is in the array of approved ips.

Resources