Error with node.js and SSL - javascript

I created all need certificate for communication between client.js and server.js.Wenn i start client.js with node client.js while server is running. I get error:self signed certificate. But i constantly have problem with ca authority. How to create valid certificate if that is a problem?
This is my client.js script:
var tls = require('tls');
var fs = require('fs');
var options = {
// These are necessary only if using the client certificate authentication (so yeah, you need them)
key: fs.readFileSync('client-private-key.pem'),
cert: fs.readFileSync('client-certificate.pem'),
// This is necessary only if the server uses the self-signed certificate
ca: [ fs.readFileSync('../server/server-certificate.pem') ]
};
var cleartextStream = tls.connect(443, options, function() {
console.log('client connected',
cleartextStream.authorized ? 'authorized' : 'unauthorized');
process.stdin.pipe(cleartextStream);
process.stdin.resume();
});
cleartextStream.setEncoding('utf8');
cleartextStream.on('data', function(data) {
console.log(data);
});
cleartextStream.on('end', function() {
server.close();
});
This is my server.js:
var tls = require('tls');
var fs = require('fs');
var options = {
key: fs.readFileSync('server-private-key.pem'),
cert: fs.readFileSync('server-certificate.pem'),
// This is necessary only if using the client certificate authentication.
// Without this some clients don't bother sending certificates at all, some do
requestCert: true,
// Do we reject anyone who certs who haven't been signed by our recognised certificate authorities
rejectUnauthorized: true,
// This is necessary only if the client uses the self-signed certificate and you care about implicit authorization
ca: [ fs.readFileSync('../client/client-certificate.pem') ]
};
var server = tls.createServer(options, function(cleartextStream) {
//Show the certificate info as supplied by the client
console.log(cleartextStream.getPeerCertificate());
console.log('server connected',
cleartextStream.authorized ? 'authorized' : 'unauthorized');
cleartextStream.write("welcome!\n");
cleartextStream.setEncoding('utf8');
cleartextStream.pipe(cleartextStream);
});
server.listen(443, function() {
console.log('server bound');
});
Error is:
Error: self signed certificate
at Error (native)
at TLSSocket.<anonymous> (_tls_wrap.js:1017:38)
at emitNone (events.js:67:13)
at TLSSocket.emit (events.js:166:7)
at TLSSocket._init.ssl.onclienthello.ssl.oncertcb.TLSSocket._finishInit (_tl
s_wrap.js:582:8)
at TLSWrap.ssl.onclienthello.ssl.oncertcb.ssl.onnewsession.ssl.onhandshakedo
ne (_tls_wrap.js:424:38)
P.S. I spent a lot of time(more then 12 hours) searching this on internet. So please no more tutorials

Related

Using a single port for bittorrent-tracker server in Heroku

I am trying to build/deploy a tracker server for use with P2P applications using the below code. It works fine locally, but when I deploy it to Heroku, the port bindings fail because only one port is allowed.
// Create a web sockets signaling server
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
//Allow all requests from all domains & localhost
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "POST, GET");
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
let lookup = {}
const hostname = '0.0.0.0';
const port = process.env.PORT;
var Server = require('bittorrent-tracker').Server
var server = new Server({
udp: false, // enable udp server? [default=true]
http: true, // enable http server? [default=true]
ws: true, // enable websocket server? [default=true]
stats: true, // enable web-based statistics? [default=true]
})
server.on('error', function (err) {
// fatal server error!
console.log(err.message)
})
server.on('warning', function (err) {
// client sent bad data. probably not a problem, just a buggy client.
console.log(err.message)
})
server.on('listening', function () {
// fired when all requested servers are listening
console.log('Signal server http port:' + server.http.address().port)
console.log('Signal server ws port:' + server.ws.address().port)
})
// start tracker server listening! Use 0 to listen on a random free port.
server.listen(port, hostname, 'listening')
// listen for individual tracker messages from peers:
server.on('start', function (addr) {
console.log('got start message from ' + addr)
Object.keys(server.torrents).forEach(hash => {
lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
console.log("peers: " + server.torrents[hash].peers.length)
})
})
server.on('complete', function (addr) {})
server.on('stop', function (addr) {})
app.get('/peers', function(req, res) {
res.send(lookup);
})
app.listen(process.env.PORT, function() {
console.log('Express server port: ' + this.address().port); //Listening on port #
})
If I use process.env.PORT for both server and app, I get the following, which is expected since Heroku only allows 1 listen port:
2021-02-13T05:35:31.016101+00:00 heroku[web.1]: State changed from starting to up
2021-02-13T05:35:30.885170+00:00 app[web.1]: Express server port: 9898
2021-02-13T05:35:30.885204+00:00 app[web.1]: listen EADDRINUSE: address already in use 0.0.0.0:9898
2021-02-13T05:35:30.885205+00:00 app[web.1]: listen EADDRINUSE: address already in use 0.0.0.0:9898
If I hard code the port for either server or app, the application launches fine, but the signaling server doesn't work. No substantial logging is generated.
2021-02-13T05:38:21.141806+00:00 heroku[web.1]: State changed from starting to up
2021-02-13T05:38:20.998054+00:00 app[web.1]: Express server port: 25702
2021-02-13T05:38:20.998550+00:00 app[web.1]: Signal server http port:31415
2021-02-13T05:38:20.998683+00:00 app[web.1]: Signal server ws port:31415
Is it possible that the bittorrent-tracker server and express server can use the same port? For instance, could I get and return the list of peers within this block of code without the need for express at all?
server.on('start', function (addr) {
console.log('got start message from ' + addr)
// Could I do something here to eliminate the need for Express?
Object.keys(server.torrents).forEach(hash => {
lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
console.log("peers: " + server.torrents[hash].peers.length)
})
})
The documentation states:
The http server will handle requests for the following paths:
/announce, /scrape. Requests for other paths will not be handled.
But perhaps there is some way I can shim in the requests that express is handling?
Not long after asking this question, it occurred to me that I might not need express at all. It turns out that was correct.
For anyone wanting a Heroku-ready bittorrent-tracker, here is the updated code:
// Create a web sockets signaling server
let lookup = {}
const hostname = '0.0.0.0';
const port = process.env.PORT;
var Server = require('bittorrent-tracker').Server
var server = new Server({
udp: false, // enable udp server? [default=true]
http: true, // enable http server? [default=true]
ws: true, // enable websocket server? [default=true]
stats: true, // enable web-based statistics? [default=true]
})
server.on('error', function (err) {
// fatal server error!
console.log(err.message)
})
server.on('warning', function (err) {
// client sent bad data. probably not a problem, just a buggy client.
console.log(err.message)
})
server.on('listening', function () {
// fired when all requested servers are listening
console.log('Signal server http port:' + server.http.address().port)
console.log('Signal server ws port:' + server.ws.address().port)
})
// start tracker server listening! Use 0 to listen on a random free port.
server.listen(port, hostname, 'listening')
// listen for individual tracker messages from peers:
server.on('start', function (addr) {
console.log('got start message from ' + addr)
Object.keys(server.torrents).forEach(hash => {
lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
console.log("peers: " + server.torrents[hash].peers.length)
})
})
server.on('complete', function (addr) {})
server.on('stop', function (addr) {})

How to make gun accept a self-signed certificate?

gun 0.8.8, Node.js-to-Node.js, Node.js-to-browser
I see the following error in browser console:
VM103:161 WebSocket connection to 'wss://127.0.0.1:8080/gun' failed: Error in connection establishment: net::ERR_INSECURE_RESPONSE
VM103:161 WebSocket connection to 'wss://10.42.0.56:8080/gun' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
And there are no messages on Node.js side.
Sorce code of my server:
const Hapi = require('hapi');
const Gun = require('gun');
const pem = require('pem');
pem.createCertificate({ days: 1, selfSigned: true }, function (err, keys) {
if (err) {
throw err
}
const server = new Hapi.Server;
var tls = {
key: keys.serviceKey,
cert: keys.certificate
};
server.connection({
port: 8080,
tls
});
server.connections.forEach(c => Gun({ web: c.listener, file: 'data.json' }));
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('Server works!');
}
});
server.start();
})
In order to make gun work with a self-signed certificate you need two things:
Lunch browser ignoring the certificate errors. For example, Chrome
google-chrome --ignore-certificate-errors
Put the following process option in Node.js code
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
or add the environment variable
export NODE_TLS_REJECT_UNAUTHORIZED=0

Is there a way to communicate with WebSocket over SSL from NativeScript app?

Currently I am writing a NS app that will communicate with a WebSocket over SSL. Here is server's code (server.js):
var fs = require('fs');
var cfg = {
port: 8082,
ssl_key: fs.readFileSync('keys/server.key'),
ssl_cert: fs.readFileSync('keys/server.crt'),
ca: fs.readFileSync('keys/ca.crt')
};
var httpServ = require('https');
var WebSocketServer = require('ws').Server;
var app = null;
// dummy request processing
var processRequest = function( req, res ) {
res.writeHead(200);
res.end("All glory to WebSockets!\n");
};
app = httpServ.createServer({
// providing server with SSL key/cert
key: cfg.ssl_key,
cert: cfg.ssl_cert,
ca: cfg.ssl.ca,
passphrase: '1234',
requestCert: true,
rejectUnauthorized: false,
}, processRequest ).listen( cfg.port );
var wss = new WebSocketServer( { server: app } );
wss.on('connection', function(ws) {
console.log("Connected!");
ws.on('message', function(message) {
console.log('received: %s', message);
});
ws.send('something');
});
Server is running well without problem. Below is the client code (wsclient.js):
const WebSocket = require('ws');
const ws = new WebSocket('wss://localhost:8082');
ws.on('open', function open() {
ws.send("dummy");
ws.on('error', function(evt) {
console.log("The socket had an error", evt.error);
});
});
When I ran the client by typing node wsclient.js, it throw the following error:
Error: unable to verify the first certificate
Obviously, the error was caused by not providing the certificate info to the request. But I have no idea how to get this done in my client code. Thanks a lot for any clues or suggestions.
Finally I found the answer:
const WebSocket = require('ws');
const ws = new WebSocket('wss://localhost:8082',{
key: fs.readFileSync('./keys/client.key'),
cert: fs.readFileSync('./keys/client.crt'),
ca: fs.readFileSync('./keys/ca.crt')
});
ws.on('open', function open() {
ws.send("dummy");
ws.on('error', function(evt) {
console.log("The socket had an error", evt.error);
});
});
Now it works!

ERR_SSL_PROTOCOL_ERROR - Socket.io and Node.js

I’m working with the Node.js server and using the Socket.io to manage connections by Socket but I’m having a problem with the SSL certificate.
Lot of users can access the Node.js server normally, but others users doesn’t access and they receive this error:
When I set my server I have this SSL options:
var privateKey = fs.readFileSync('/root/cert/key.key', 'utf8').toString();
var certificate = fs.readFileSync('/root/cert/cert.crt', 'utf8').toString();
var ca = fs.readFileSync('/root/cert/ca.crt').toString();
var credentials = { key: privateKey, cert: certificate, ca: ca };
var app = express();
var httpsServer = https.createServer(credentials, app);
var io = require('socket.io')(httpsServer);
Somebody knows how to resolve this error? The problem is only some users receive this error.
Well, as far as I can see, you are missing a listening port for you https server.
var httpsServer = https.createServer(credentials, app).listen(<port>);
I had so much trouble with ERR_SSL_PROTOCOL_ERROR that I have to give you my solution
NodeJS server 16.15.0 with "socket.io": "2.4.1" (I assume it works with other NodeJS versions)
const path = require("path");
const fs = require("fs");
const io = require("socket.io")();
const folder = path.join(__dirname, "ssl");
const privateKey = fs.readFileSync(path.join(folder, "server_key.pem"), "utf8");
const certificate = fs.readFileSync(path.join(folder, "server_cert.pem"), "utf8");
const optSsl = {
key: privateKey,
cert: certificate,
ca: [certificate],
requestCert: false, // put true if you want a client certificate, tested and it works
rejectUnauthorized: false,
};
const server = require("https");
const webServer = server.createServer(optSsl);
webServer.listen(8025); // port number
io.listen(webServer);
io.on("connection", (client) => {
/*...*/
});
/*...*/
Angular 10.2.7 with "ngx-socket-io": "3.2.0" (I assume it works also with other Angular versions)
import { Socket, SocketIoConfig } from 'ngx-socket-io';
/*...*/
socket: Socket;
socketConfig: SocketIoConfig;
socketConfig = {
url: "https://myserver:8025",
options: {},
};
socket = new Socket(socketConfig);
socket.connect();
Looks like your apache2 is not properly configured.
Check if you have your config file enabled:
a2ensite default-ssl
And then restart the server.

Node.js error with SSL UNABLE_TO_VERIFY_LEAF_SIGNATURE

System: Windows 7
NodeJS version: 0.10.2
WS module: ws, last version
Error:
events.js:72
throw er; // Unhandled 'error' event
^
Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE
at SecurePair. (tls.js:1283:32)
at SecurePair.EventEmitter.emit (events.js:92:17)
at SecurePair.maybeInitFinished (tls.js:896:10)
at CleartextStream.read [as _read] (tls.js:430:15)
at CleartextStream.Readable.read (_stream_readable.js:294:10)
at EncryptedStream.write [as _write] (tls.js:344:25)
at doWrite (_stream_writable.js:211:10)
at writeOrBuffer (_stream_writable.js:201:5)
at EncryptedStream.Writable.write (_stream_writable.js:172:11)
at write (_stream_readable.js:547:24)
Server:
(function(){
"use strict";
var fs = require('fs');
// you'll probably load configuration from config
var cfg = {
ssl: true,
port: 8080,
ssl_key: 'crt/server1.key',
ssl_cert: 'crt/server1.crt'
};
var httpServ = require('https')
var WebSocketServer = require('ws').Server;
var app = null;
// dummy request processing
var processRequest = function( req, res ) {
res.writeHead(200);
res.end("All glory to WebSockets!\n");
};
if ( cfg.ssl ) {
app = httpServ.createServer({
// providing server with SSL key/cert
key: fs.readFileSync( cfg.ssl_key ),
cert: fs.readFileSync( cfg.ssl_cert ),
//requestCert: true,
//rejectUnauthorized: false
}, processRequest ).listen( cfg.port );
} else {
app = httpServ.createServer( processRequest ).listen( cfg.port );
}
// passing or reference to web server so WS would knew port and SSL capabilities
var wss = new WebSocketServer( { server: app } );
wss.on( 'connection', function ( wsConnect ) {
wsConnect.on( 'message', function ( message ) {
console.log( message );
});
});
}());
Client:
var WebSocket = require('ws');
var ws = new WebSocket('wss://localhost:8080');
ws.on('open', function() {
ws.send('something');
});
The certificate confirmed.
Help> please!
I'm using a package called "superagent" and getting the same error. After trying several potential fixes, I came across this one that works for me 100% of the time:
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
There's no need to do any requires or whatever : just add this to your code before your network calls and you're good to go.
The SSL certificate used by the server in your example is probably not fully trusted by the WebSocket client so NodeJS is throwing an error in its network library on the client-side.
You need to set rejectUnauthorized to false (this is an option that most high-level network libraries will allow you to set via an option that gets passed to the lower level NodeJS networking library).
I skimmed the ws module source code and looks like you should try this:
var ws = new WebSocket('wss://localhost:8080', null, {rejectUnauthorized: false});
NOTE: rejectUnauthorized should only be false during testing/development. Production applications should always use rejectUnauthorized: true for full security.
If you do not want to disable your security. Add ca: [cert] option in http /socket client options.
Where cert is Certificate of server you are connecting to or CA of the server you are connecting to.
I've encountered a similar problem before, you may try to use
https.globalAgent.options.secureProtocol = 'SSLv3_method'
to set SSLv3 connection for https.
As per the nginx official website, they clearly mentioned certificate should be the combination of The server certificate and chained certificates.MoreInfo
Below solution is prefect and working fine for me in node js
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
Use a library to load the certificates (pem, crt, ...) from a given folder.
https://github.com/fujifish/syswide-cas
You can export the certificates from the browser and try:
const syswidecas = require('syswide-cas');
syswidecas.addCAs('./certs');

Categories

Resources