Grunt Node and Express Local Dev HTTPS Certificates - javascript

I'm trying to make a start at Service Workers and read you require to have an ssl cert.
I've Got an AngularJS 1.x application and a Node Express back end, and I run both independently so I I use grunt serve to run the front end on port 8443 and I use node app.js to run express which is on 7443.
note: I'm doing this on macOS
I used the guide on how to set up https on a project that uses Grunt: here
openssl genrsa -out livereload.key 1024
openssl req -new -key livereload.key -out livereload.csr
openssl x509 -req -in livereload.csr -signkey livereload.key -out livereload.crt
Gruntfile.js
options: {
protocol: 'https', // or 'http2'
port: 8443,
hostname: '0.0.0.0',
key: grunt.file.read('livereload.key'),
cert: grunt.file.read('livereload.crt')
},
node app.js
var privateKey = fs.readFileSync('../livereload.key', 'utf8');
var certificate = fs.readFileSync('../livereload.crt', 'utf8');
var credentials = {key: privateKey, cert: certificate};
httpsServer.listen(7443, config.ip, function () {
console.log('Express server listening on %d, in %s mode', 7443, app.get('env'));
});
Both start with no errors, the front end does complain the connection is not private. When my front end tried to hit an endpoint on the express server I receive the following;
OPTIONS https://localhost:7443/api/census/general net::ERR_INSECURE_RESPONSE
Could someone please assist on this problem of mine.

You have created a self-signed certificate, which is fine for development and testing but is considered unsafe for general use. Unlike SSL certificates purchased from reputable third-parties, self-signed certificates are untrusted by default.
You will need to tell your OS to explicitly trust the certificate. I'm unfamiliar with Mac OS but this question was previously answered on SuperUser.

Related

Error setting up wss server: works on localhost, but not with ip address

I'm having issues setting up a wss server (Secure Websocket Server) in node.js.
When we run the server and test it using an online websocket tester and connect to wss://localhost:8888 it works. But when we connect to wss://my_ip:8888 (ip found with ifconfig) it results in the error index.js:15 WebSocket connection to 'wss://192.168.1.217:8888/' failed.
I've made a git repository for easy testing: https://github.com/DaanS8/wss_error
Possible useful info
We pinged the ip on the port 8888 with `telnet my_ip 8888` which was successful. Any other port fails, which means it is listening?
Chrome behaves differently then Firefox, in chrome localhost works but in Firefox localhost doesn't even work whilst using the same tests on the online websocket tester.
The code is running on a ubuntu vm on a windows machine. It seems the ubuntu vm doesn't have its own firwall (sudo ufw status results in error), just turning of the windows firewall doesn't change the errors.
The certificates were generated with the following commands:
openssl genrsa -des3 -out myCA.key 2048
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem
Enter pass phrase for myCA.key:
Country Name (2 letter code) [AU]:BE
State or Province Name (full name) [Some-State]:Vlaams-Brabant
Locality Name (eg, city) []:Leuven
Organization Name (eg, company) [Internet Widgits Pty Ltd]:KU Leuven
Organizational Unit Name (eg, section) []:Pno
Common Name (e.g. server FQDN or YOUR name) []:Team x
Email Address []:xxxx#xxxxxxxx.be
openssl rsa -in myCA.key -text > private.pem
My main sources:
https://deliciousbrains.com/ssl-certificate-authority-for-local-https-development/
How to Create Secure(TLS/SSL) Websocket Server
main.ts was copied from a blog post that I temporarily can't find anymore
Code
main.ts:
// Minimal amount of secure websocket server
var fs = require('fs');
// read ssl certificate
var privateKey = fs.readFileSync('certs/private.pem', 'utf8');
var certificate = fs.readFileSync('certs/myCA.pem', 'utf8');
var credentials = { key: privateKey, cert: certificate };
var https = require('https');
//pass in your credentials to create an https server
var httpsServer = https.createServer(credentials);
httpsServer.listen(8888);
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({
server: httpsServer
});
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
ws.send('reply from server : ' + message)
});
ws.send('something');
});
See github for keys etc.
Your "online websocket tester" doesn't provide easily readible source code, so it is not clear what is failing. My guess: TLS cert validation is failing. (Browsers may have own rules for localhost, so it may be working for localhost in some browsers).
You are connecting to the IP, but cert is generated Common Name: Team x. Correct TLS client implementation should reject this kind of TLS connection, because server name is not matching TLS CN name ('IP'!='Team x').
Solutions:
1.) Generate proper TLS certificate, where Common Name is matching used IP. This is a proper secure solution for your use case (usually server FQDN is used, because domain is used for connection and not the server IP).
2.) Use websocket client, which provides option to disable cert verification.
3.) Open https://IP:8888 and add browser TLS exception for used cert. Exception should be applied also for wss protocol then.
Try using cloudflaired
for download : Click here
tutorial : Click here
it may be the problem of firewall rules, and other factors
EDIT:
This program packs a lightweight server that acts as a bridge from your computer to cloudflair servers. This hosts the site on a temporary subdomain for free
if you are having a cloudflair account, it will help with setting and configuring static permanent urls instead of dynamically changing every time
Sorry I don't know about the pricing as I use the free plan
for more info visit the docs
Because of this it can bypass many windows restrictions (like firewall) isp restrictions (like nat), etc. So you can focus on the project
Also this works even out of your lan. Just so you know it also works outside the lan. so to share a quick preview to others.

Run vuejs development server with SSL (to serve over HTTPS)

Important Detail & Workaround: I've come across this: "Deprecating Powerful Features on Insecure Origins"
This explains that HTTPS is enforced on external hosts. I have my development environment on my laptop and, on the weekend I SSH into that box, which is why I ran into this problem yesterday. I run the vuejs dev server remotely on the laptop, making it listen to 0.0.0.0 and open the page on my desktop. This causes the problem.
I've tried using SSH port forwarding to localhost. This worked and is an acceptable workaround for me.
The original question still remains valid. I will leave it open for now.
I'm working with a JS API which requires SSL (WebRTC). So to do development, I need to run the dev server over HTTPS. How can I do that with vuejs?
I've quickstarted the project using webpack. I found some links explaining how to run webpack-dev-server over SSL but I don't know how to do that with a vuejs application. I'm incredibly green considering everything that's JavaScript & NPM. The webpack links all mention a config file, but there is no such file in my project. The closest I see is the "main.js" but there is absolutely no configuration in there.
In essence, what I have is the result of the following steps:
mkdir demo
cd demo
npm install --save-dev vue-cli
./node_modules/.bin/vue init vuetifyjs/webpack-advanced demo
# Use the defaults here (except for "Vue build" I used "Runtime-only")
cd demo
npm install
npm run dev # <-- This is the command I would like to use SSL in
I don't know if you still have this problem or if any other person still encounters it but I found a solution.
Follow the instruction above to generate an openssl key and cert in your working folder.
In /node_modules/webpack-dev-server/bin/webpack-dev-server.js change this line from:
key: {
type: 'string',
describe: 'Path to a SSL key.',
group: SSL_GROUP
},
cert: {
type: 'string',
describe: 'Path to a SSL certificate.',
group: SSL_GROUP
},
to:
key: {
type: 'string',
describe: fs.readFileSync('key.pem'),
group: SSL_GROUP
},
cert: {
type: 'string',
describe: fs.readFileSync('cert.pem'),
group: SSL_GROUP
},
then set
argv.https = true;
That is all I had to do to have my code served from https.
Note that the command line will still read http://localhost:8080, but when you use https in the browser, your app will be displayed after warning from the browser
Requirement openssl installed :
First we have to generate SSL certificat based on a key made by openssl and without pass phrase cos this will generate an error.
nodejs https>node server.js
_tls_common.js:87
c.context.setKey(options.key);
^ Error: error:0907B068:PEM routines:PEM_READ_BIO_PRIVATEKEY:bad password read ...
Go inside your project start to create key & certificat :
openssl req -nodes -new -x509 -keyout key.pem -out cert.pem -days 365
-nodes : Don't encrypt the private keys at all.
Install the packages needed for your project : (--save to add to package.json)
npm install express --save
npm install https --save
npm install fs --save
now create the server file :
touch server.js
nano server.js
Copy/Paste : to server.js
var fs = require('fs');
var https = require('https');
var app = require('express')();
var options = {
key : fs.readFileSync('key.pem'),
cert : fs.readFileSync('cert.pem')
};
app.get('/', function (req, res) {
res.send('Hello World!');
});
https.createServer(options, app).listen(3000, function () {
console.log('Started!');
});
In this cas we don't use 443 port because is already used by services, so i use the port 3000 unused by any app...

Node.js https connection using a modern cipher not working

I used OpenSSL to generate a certificate with the following steps:
~/openssl genrsa -out server.key 2048
~/openssl req -new -x509 -key server.key -out server.crt -days 730
And then loaded these files into node.js
var https = require('https');
var privateKey = fs.readFileSync('./server.key', 'utf8');
var certificate = fs.readFileSync('./server.crt', 'utf8');
var credentials = {
key: privateKey,
cert: certificate
};
var app = express();
var httpsServer = https.createServer(credentials, app);
This way, my server was running as expected. But in Chrome, when i click View Site Information, it was saying that I use an "obsolete cipher suite"..
So I checked Google's certificate, and it was saying a "modern cipher suite".
Only difference between my self-signed certificate and Google's was the Key Exchange Algorithm which was RSA on my side and ECDHE_ECDSA on Google's side.
So I decided to create a new certificate using;
~/openssl ecparam -name prime256v1 -genkey -param_enc explicit -out server.key
~/openssl req -new -x509 -key server.key -out server.crt -days 730
Files are created, and node.js gives no error about anything. But when I try to connect to server, my browser simply closes the connection (ERR_CONNECTION_CLOSED) with no indication of error on both server and client side.
I tried different private keys with different parameters but no luck. A simple error message somewhere would help a lot but I'm stuck for hours Googling about how to create Modern Ciphers, trying those out and end up having nothing.
So my question is, how am I supposed to create a self-signed strong/modern cipher (with openssl) that can work with Node.js https module?

Express and SSL usage

I've purchased a Comodo SSL certificate to make SSL server with express. I have these files.
AddTrustExternalCARoot.crt
COMODORSAAddTrustCA.crt
COMODORSADomainValidationSecureServerCA.crt
mysite.com.key
mysite.com.csr
mysite_com.crt
According to a lot of documents I need .pem files. But nobody is saying what is that .pem files?
var options = {
key: fs.readFileSync('/key.pem'),
cert: fs.readFileSync('/cert.pem'),
ca: fs.readFileSync('/ca.pem')
};
It'd be great if there is a tutorial.
Try this answer. PEM is just a format than other SSL formats, and is very common.
Comodo may have already provided you a .pem file, but just named it .crt.
OR you may be able to request a .pem file in place of a DER-formatted file.
OR, you can use OpenSSL to convert from one format to another.
openssl rsa -inform DER -outform PEM -in mysite.com.key -out mysite.com.key.pem
openssl x509 -inform DER -outform PEM -in mysite.com.crt -out mysite.com.crt.pem
Simply start ssl OR simple way to use PEM NPM
var https = require('https'),
connect = require('connect'),
fs = require("fs");
var port = 3000;
var options = {
key: fs.readFileSync('/key.pem'),
cert: fs.readFileSync('/cert.pem'),
ca: fs.readFileSync('/ca.pem')
};
var app = express();
/* express setting */
server = require('https').createServer(options, app),
server.listen(port);
PEM npm is easiest way to start node server with SSL
like
$> npm install pem
var https = require('https'),
pem = require('pem'),
express = require('express');
pem.createCertificate({days:1, selfSigned:true}, function(err, keys){
var app = express();
https.createServer({key: keys.serviceKey, cert: keys.certificate}, app).listen(443);
});

NodeJs tls.createServer equivalent to Apache SSLCertificateChainFile?

I have an Apache config for SSL like so:
SSLCertificateFile ~/certs/server.crt
SSLCertificateKeyFile ~/certs/server.key
SSLCertificateChainFile ~/certs/bundle.crt
Now in my NodeJs server, I am using grunt with grunt-connect as the server.
The documentation for grunt-connect says that it can be configured using the following syntax.
grunt.initConfig({
connect: {
server: {
options: {
protocol: 'https',
port: 8443,
key: grunt.file.read('server.key').toString(),
cert: grunt.file.read('server.crt').toString(),
ca: grunt.file.read('ca.crt').toString()
},
},
},
});
I need this configuration to match my Apache configurations. It has a certificate file, and a key file, and also a bundle file.
Looking at the documentation for the tls.createServer in NodeJs,
I do not see an option that looks like it could be equivalent to SSLCertificateChainFile.
How can I make my NodeJs connect server mirror the same SSL configuration as my Apache server?
EDIT
I will also award the bounty to someone who can do this:
Create a SSCCE Gruntfile that demonstrates how to configure connect to accept a server certificate and bundle certificate.
You may try concatenating server.crt and ca.crt files in one file and using result in cert option. Don't use ca option, as per docs it is needed only 'if the client uses the self-signed certificate'.

Categories

Resources