Launch a nodejs server on AWS EC2 with SSL certificate - node.js

I tried to configure server with https. On local server, the local private key and certificate works. The code is:
var https = require('https');
const options = {
key: fs.readFileSync('./privatekey.key'),
cert: fs.readFileSync('./certificate.crt')
};
var server = https.createServer(options, app);
But when I purchased a SSL certificate and try to use it on the AWS server, it didn't work at all.
var https = require('https');
const options = {
key: fs.readFileSync('privatekey.pem'),
cert: fs.readFileSync('./ssl/portal.crt'),
ca: [fs.readFileSync('./ssl/portal.ca-bundle')]
};
It always showed webpage is not available. I also tried to upload the server certificate to AWS configuration, still failed. Does anyone know how to fix this?

Related

Express.js. How to generate a valid ssl certificate?

I have a production ready express server. And 2 webapps working with it.
The express server is in the port : 1111
I have created two letsencrypt ssl for my nginx server, and im using it with the frontend sites for app.domain.com and domain.com, it works fine.
The point is that the backend isnt reached because it must be ssl too. But... how do I setup a valid ssl for my backend? I mean I cant do it with letsencrypt because its a backend server and it doesn't have ssl.
I have tried using the same certificates that i generated for domain.com in the express server using basically this code taken from other site
// Dependencies
const fs = require('fs');
const http = require('http');
const https = require('https');
const express = require('express');
const app = express();
// Certificate
const privateKey = fs.readFileSync('/etc/letsencrypt/live/yourdomain.com/privkey.pem', 'utf8');
const certificate = fs.readFileSync('/etc/letsencrypt/live/yourdomain.com/cert.pem', 'utf8');
const ca = fs.readFileSync('/etc/letsencrypt/live/yourdomain.com/chain.pem', 'utf8');
const credentials = {
key: privateKey,
cert: certificate,
ca: ca
};
app.use((req, res) => {
res.send('Hello there !');
});
// Starting both http & https servers
const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);
httpServer.listen(80, () => {
console.log('HTTP Server running on port 80');
});
httpsServer.listen(443, () => {
console.log('HTTPS Server running on port 443');
});
But it worked randomly, a lot of times the request timed out because it took forever, and other times it worked, it was weird.
But now it suddenly even stopped working, so I dont know what to do there.
What type of certificate do I have to use?
Self signed ones are rejected by chrome, and I donty know how else to generate a letsencrypt one, if the express node server is running in an ip not a domain
Okey, the problem was with my nginx virtualhosts. I created a virtualhost api.domain.com
server
{
listen 443;
listen [::]:443;
server_name api.domain.com;
location /
{
proxy_pass https://127.0.0.1:1111;
}
}
And then run
sudo certbot --nginx -d api.domain.com
Then it started to work

SSL certificate on NodeJS and express not working

I have a NodeJs Application running with express. I have been trying to integrate an SSL certificate but I keep having the same error: Error: error:0906D06C:PEM routines:PEM_read_bio:no start line.
I have tried some solutions I found on stackOverflow like
var privateKey = fs.readFileSync( 'privatekey.pem' );
var certificate = fs.readFileSync( 'certificate.pem' );
https.createServer({
key: privateKey,
cert: certificate
}, app).listen(port);
or
var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey = fs.readFileSync('privatekey.pem');
var certificate = fs.readFileSync('certificate.pem');
var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);
httpServer.listen(8081);
httpsServer.listen(8443);
But none seem to work. My main problem is that I donwloaded my certificate file from GoDaddy but I only get two .cert files. I have read in some websites how to obtain the .pem files but I keep getting the same error.
As you can see I am new at using https protocol in NodeJs.
Could you help me solve this problem?
Best regards

Nodejs TLS with self-signed Certificate Authority

Background:
I'm trying to communicate between a server and one (should be able to be multiple - hence the need of a CA) client through TLS.
Each node has a certificate that is signed with a common CA.
The CA is in turn self-signed.
The private key of each node is exported as key.pem.
The certificate of each node is exported as certificate.crt.
The CA certificate is exported as ca.crt.
The certificates are not bundled, just exported as is.
The server uses the following setup:
var tls = require("tls");
var fs = require("fs");
var options = {
key: fs.readFileSync("keys/key.pem", "utf8"),
cert: fs.readFileSync("keys/certificate.crt", "utf8"),
requestCert: true,
rejectUnauthorized: true,
ca: [fs.readFileSync('keys/ca.crt')]
}
var server = tls.createServer(options, function(res) {
console.log("Client connected");
console.log('Client connected',
res.authorized ? 'authorized' : 'unauthorized');
res.write("Hello World!");
res.setEncoding("utf8");
res.pipe(res);
}).listen(3000);
The client uses the following setup:
var tls = require("tls");
var fs = require("fs");
var options = {
key: fs.readFileSync("keys/key.pem", "utf8"),
cert: fs.readFileSync("keys/certificate.crt", "utf8"),
requestCert: true,
rejectUnauthorized: true,
ca: [fs.readFileSync('keys/ca.crt')]
}
var client = tls.connect(3000, options, function(){
console.log("Connected to server");
console.log(client.authorized ? "Authorized" : "Not authorized");
});
client.on("data", function(data){
console.log("Received from server", data);
client.end();
});
Note on keys / certificates:
The keys and certificates are generated with the openssl GUI / manager XCA.
The tree looks as follows:
The problem:
As you can see I am using explicit client certificate authentication and I want to disallow any non-permitted connections.
The problem with this is that the client is not able to connect, even though all the certificates come from the same CA.
The error I get from both the server (when a client connects) and the client(when it connects) is:
Error: socket hang up, code: ECONNRESET
If I disable rejectUnauthorized the client can connect, but res.authorized returns false.
What is causing authorised clients to not being able to be authenticated?
Your code is fine. I expect there is a problem with your certificates. The fact that there is no expiry date sticks out to me. I have found this OpenSSL Certificate Authority by Jamie Nguyen to be very useful.
Remember that Nodejs does not support multiple certificates in one cert file, so if you are following the guide, there is no need to copy the root ca and intermediate ca into one file. You will have to add them as separate file entries in the ca list argument.
Afaik the xca tool is build on openssl, so might be able to map the commands in openssl to xca.

How to use external certificate for HTTPS in nodejs

my nodejs server currently uses a self-signed certificate as follows:
var sslOptions = {
key: fs.readFileSync('./self-ssl/server.key'),
cert: fs.readFileSync('./self-ssl/server.crt'),
ca: fs.readFileSync('./self-ssl/ca.crt'),
requestCert: true,
rejectUnauthorized: false
};
https = require('https').createServer(sslOptions, app);
I want to change this to use a 3rd party certificate, I have received a RapidSSL certificate for my domain which is copied in ./ssl/mactester_com_ee.crt.
My question is how do I edit the old self-signed code to use the new 3rd party certificate?
Thanks,
Found the answer:
var sslOptions = {
key: fs.readFileSync('./ssl/server_private.key'),
cert: fs.readFileSync('./ssl/3rdparty.crt'),
};
https = require('https').createServer(sslOptions, app);

NodeJS SSH authentication host and command execution

I want to have a NodeJS application to which I can connect over SSH with a public key and send some data to. To be more explicit it should go as follow:
NodeJS application has some functions written
From a server I ssh the nodejs application and tries to identify me by my public key
After I am authenticated, I can send some strings to it, the app is going to parse the string and execute different functions
The only problem is that I cannot manage to do this with any SSH npm package existing. I want the nodejs app to just accept SSH connection and do the authentication and wait for some strings. Is this possible?
EDIT: I want to go with this approach because I only want to call the node functions to execute something only from some allowed clients (servers) and I don't want to send those requests via HTTP so anyone could access it
You're probably better off using HTTPS with client certificates rather than using an SSH server within node (although you can do that with the ssh module, a binding to libssh2), if you want to use certificates.
Here's how you'd set up the HTTPS server:
var https = require('https'),
fs = require('fs');
var options = {
key: fs.readFileSync('server.key'), // server private key
cert: fs.readFileSync('server.crt'), // server certificate
ca: fs.readFileSync('server_ca.crt'), // server CA, this can be an array of CAs too
requestCert: true
};
https.createServer(options, function(req, res) {
if (req.client.authorized) {
res.writeHead(200);
res.end('Hello world!');
} else {
res.writeHead(401);
res.end();
}
}).listen(443);
Then it's just a matter of generating a client certificate using the server's CA that you use with your HTTPS client.
For connecting to the HTTPS server:
For cURL, the command line would look something like: curl -v -s --cacert server_ca.crt --key client.key --cert client.crt https://localhost or to skip server verification: curl -v -s -k --key client.key --cert client.crt https://localhost
For node.js, you might use client code like:
var https = require('https'),
fs = require('fs');
var options = {
// normal http.request()-specific options
method: 'GET',
path: '/',
// tls.connect()-specific options
key: fs.readFileSync('client.key'), // client private key
cert: fs.readFileSync('client.crt'), // client certificate
ca: fs.readFileSync('server_ca.crt'), // server CA, this can be an array of CAs too
// or comment out the `ca` setting and use the following to skip server verification,
// similar to cURL's `-k` option:
//rejectUnauthorized: false
};
https.request(options, function(res) {
if (res.statusCode === 200)
console.log('Accepted!');
else
console.log('Rejected!');
// drain and discard any response data
res.resume();
}).end();

Resources