How to use HTTPS with Node.js - node.js

I have little experience with HTTPS, SSL, etc.
I want to know how to use Node.js with HTTPS. I know how to use node.js fine, but when using HTTPS it gives errors.
I think I need to install something (openSSL?). I would like to be told of ALL the things I have to install on a windows 8.1 computer (no, I do not want to get any form of linux. No cygwin either), in order to use a node.js HTTPS server.
I do not need to have a paid certificate, I just need to have it work. It's not receiving requests from a browser, so I don't care about a paid certificate.

Once you have node.js installed on your system, just follow the procedure below to get a basic web server running with support for both HTTP and HTTPS!
Step 1 : Build a Certificate Authority
create the folder where you want to store your key & certificate :
mkdir conf
go to that directory :
cd conf
grab this ca.cnf file to use as a configuration shortcut :
wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/ca.cnf
create a new certificate authority using this configuration :
openssl req -new -x509 -days 9999 -config ca.cnf -keyout ca-key.pem -out ca-cert.pem
now that we have our certificate authority in ca-key.pem and ca-cert.pem, let's generate a private key for the server :
openssl genrsa -out key.pem 4096
grab this server.cnf file to use as a configuration shortcut :
wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/server.cnf
generate the certificate signing request using this configuration :
openssl req -new -config server.cnf -key key.pem -out csr.pem
sign the request :
openssl x509 -req -extfile server.cnf -days 999 -passin "pass:password" -in csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem
Step 2 : Install your certificate as a root certificate
copy your certificate to your root certificates' folder :
sudo cp ca-crt.pem /usr/local/share/ca-certificates/ca-crt.pem
update CA store :
sudo update-ca-certificates
Step 3 : Starting your node server
First, make sure the code of your server.js looks something like this :
var http = require('http');
var https = require('https');
var fs = require('fs');
var httpsOptions = {
key: fs.readFileSync('/path/to/HTTPS/server-key.pem'),
cert: fs.readFileSync('/path/to/HTTPS/server-crt.pem')
};
var app = function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}
http.createServer(app).listen(8888);
https.createServer(httpsOptions, app).listen(4433);
go to the directory where your server.js is located :
cd /path/to
run server.js :
node server.js

2022 Answer
Get your node.js server working with HTTP on port 80
Use DNS to map <YourWebsite.com> to your server
Use https://certbot.eff.org to upgrade your server to HTTPS
In step 3 you download and run the Certbot app on your server. Certbot asks for "YourWebsite.com". Then it issues you with a new HTTPS certificate and patches your server config files to use the HTTPS certificate.
For example, my node server was running in AWS EC2 listening on port 3000. I found Ubuntu was easier to configure than Amazon's own Linux. I used AWS Route53 to map a domain name to my EC2 instance with a static Elastic IP address. I had installed Nginx in EC2 to map clients' port 80 requests to my server on port 3000. The Certbot automatically patched the Nginx config files to use the new HTTPS certificates.
Certbot is easy. This is because Certbot runs on your server, so the HTTPS certification authority (LetsEncrypt) can verify that you control the domain name by talking over the internet to Certbot.

Related

SRS how enable HTTPS for HLS stream?

I use Ubuntu 16 server with apache and let's encrypt certificates. I have compiled SRS today directly from Git, so I have the latest version. I'm trying to enable HTTPS on all site, I have a player which load HSL stream passed by RTMP. How can I enable SSL? Now I receive the connection closed error. I've tried to move the path of HLS stream to one folder covered by certificate with no results.
This is the link for SRS: https://github.com/ossrs/srs
If someone needs more detail I can reply.
If you use NGINX or CaddyServer, you could set HTTPS proxy for SRS, please read #2881, it works like this:
OBS --> SRS --HTTP--> NGINX --HTTPS--> Viewers
Note: It's a HTTPS reverse proxy, if you need a HLS cluster, please read this.
However, ossrs/srs has support for https but they don't enable it by default. So do this to enable https
I install ossrs/srs by using docker, default config uses port 8088 for https so remember to expose that port for docker
docker run -d -p 1935:1935 -p 1985:1985 -p 8080:8080 -p 8088:8088 \
ossrs/srs:v4 ./objs/srs -c conf/srs.conf
Change http_server part in config file '/usr/local/srs/conf/srs.conf'
Change from
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
To
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
https {
# Whether enable HTTPS Streaming.
# default: off
enabled on;
# The listen endpoint for HTTPS Streaming.
# default: 8088
listen 8088;
# The SSL private key file, generated by:
# openssl genrsa -out server.key 2048
# default: ./conf/server.key
key ./conf/server.key;
# The SSL public cert file, generated by:
# openssl req -new -x509 -key server.key -out server.crt -days 3650 -subj "/C=CN/ST=Beijing/L=Beijing/O=Me/OU=Me/CN=ossrs.net"
# default: ./conf/server.crt
cert ./conf/server.crt;
}
}
Remember to upload your server.key and server.crt to conf folder (you can generated self signed certificate by comment guidelines above)
Restart docker to complete

Self signed certificate: I am missing the relation between browser and server

I created a Self Signed certificate using openSSL using this command:
openssl req -x509 -out localhost.crt -keyout localhost.key \
-newkey rsa:2048 -nodes -sha256 \
-subj '/CN=localhost' -extensions EXT -config <( \
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
I have a Express/Node server using it through this code:
https
.createServer(
{
key: fs.readFileSync("/Users/Me/.localhost-ssl/localhost.key"),
cert: fs.readFileSync("/Users/Me/.localhost-ssl/localhost.crt")
},
app
)
.listen(8080, () => console.log(env + " Server listening on port 8080"));
I started this server and it's running through https. I have a client (based on create-react-app) running in the same machine, different port, trying to connect to this server on port 8080.
On the first run, I trusted the certificate after Chrome said that it was invalid and, as the picture below shows, my client app does not complain about the certificate:
However, the client can't retrieve data from the server. The client shows this error:
Here my keychain picture, showing this certificate:
What is missing? Do I need 2 certificates in my keychain? Because I am running the client and the server in the same machine.

Node.js HTTPS configuration error - no common encryption algorithm(s)

I have seen other similar questions but non addresses my problem. I have generated my TLS (openSSL) Self-Signed certificate, but seems not working on my NodeJS server.
Instructions to generate SSL
openssl req -newkey rsa:2048 -keyout key.pem -x509 -days 365 -out certificate.pem
openssl x509 -text -noout -in certificate.pem
openssl pkcs12 -inkey key.pem -in certificate.pem -export -out certificate.p12
openssl pkcs12 -in certificate.p12 -noout -info // verify certificate
So at the end I have .p12 also known as PFX type certificate. Below is my Node.js code:
// ------- Start HTTPS configuration ----------------
const options = {
pfs: fs.readFileSync('./server/security-certificate/certificate.p12'),
passphrase: 'secrete2'
};
https.createServer(options, app).listen(8443);
// -------- End HTTPS configuration -----------------
// Also listen for HTTP
var port = 8000;
app.listen(port, function(){
console.log('running at localhost: '+port);
});
Here is the output when I run curl command, the HTTP request is served correctly, only HTTPS has problem:
Moreover, if I do this:
export CURL_CA_BUNDLE=/var/www/html/node_app/server/security-certificate/cert.p12
Then I get following error:
curl: (77) Problem with the SSL CA cert (path? access rights?)
If I try to access in browser with HTTPS and port, browser says it could not load the page.
Reference links I followed:
Node.js HTTPS:
https://nodejs.org/dist/latest-v8.x/docs/api/https.html#https_https_createserver_options_requestlistener
I'm using AWS RedHat Linux
So far don't know the solution to the above posted problem related to my .p12 bundle certificate (used in my Node.js configuration).
However I have noticed that when I changed the code and tried to use the .pem certificate, it worked correctly with curl -k <MY-URL> command.
const options = {
cert: fs.readFileSync('./server/security-certificate/cert.pem'),
key: fs.readFileSync('./server/security-certificate/key.pem'),
//pfs: fs.readFileSync('./server/security-certificate/cert.p12'), // didn't work
passphrase: 'secrete'
};
https.createServer(options, app).listen(8443);
If any one knows better solution/answer please post that. So far, I'm not sure why .p12 certificate does not work. Should I rename it to .pfx (what is the different and effect)?

Self-signed certificate issue on setup webhhok for Facebook-messenger bot application

I get this error when i tried to set webhook url for facebook messenger bot:
The URL couldn't be validated. Callback verification failed with the following errors: curl_errno = 60; curl_error = SSL certificate problem: self signed certificate in certificate chain; HTTP Status Code = 200; HTTP Message = Connection established
First i created certificate.
1) I used this config file and created certificete authority:
openssl req -new -x509 -days 9999 -config ca.cnf -keyout ca-key.pem -out ca-crt.pem
2) I generated a private key
openssl genrsa -out server-key.pem 4096
Then i generated certificate signing request using this configuration file
openssl req -new -config server.cnf -key server-key.pem -out server-csr.pem
After that i executed command:
openssl x509 -req -extfile server.cnf -days 999 -passin "pass:password" -in server-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out server-crt.pem
I didn't chnage any property in configuration files.
Then installed my certificate on windows server by this way
On my Node.js app i created https server using this options:
var server = https.createServer({
ca: fs.readFileSync('sslcert/ca-crt.pem', 'utf8'),
key: fs.readFileSync('sslcert/server-key.pem', 'utf8'),
cert: fs.readFileSync('sslcert/server-crt.pem', 'utf8')
}, app); server.listen(port);
And when i tried to set webhook i got above error. If i open my webhook url on browser i am getting
NET::ERR_CERT_AUTHORITY_INVALID
if ignore this error application console shows status 200
That's right, the URL couldn't be validated because your self signed certificate is in the certificate chain. This is expected behavior.
Self signed certificates are fine for just encrypting the connection, but they don't convey the other important part of proving third party validation that the provider is who they say they are, which is what validation is.
You'll need to get a cert that carries this validation to validate your callback URL. You can purchase one from a reputable vendor, or you can use a service like StartSSL to get one for free (I'm not associated with them in any way, I've just had good experience with them).
You follow THIS and use letsencrypt after that you will get these four files
1.cert.pem 2.chain.pem 3.fullchain.pem 3.privkey.pem
chain.pem is CA file.
Here I also have written a small code snippet to use these.

Running a simple HTTPS Node JS Server on Amazon EC2

I'm trying to create a simple https server on Amazon EC2 to test a third party API.
Here are the steps I've followed:
Created an Amazon EC2 instance, and opened up HTTP and HTTPS ports:
Created simple ssl credentials using
openssl genrsa 2048 > privatekey.pem
openssl req -new -key privatekey.pem -out csr.pem
openssl x509 -req -days 365 -in csr.pem -signkey privatekey.pem -out
server.crt
Created a simple node js server
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('./privatekey.pem'),
cert: fs.readFileSync('./server.crt')
};
https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8080);
When I run the server, and attempt to connect to it using url https://ec2-XX-XXX-XXX-XXX.compute-1.amazonaws.com/, I keep getting a connection refused.
A telnet test also produces:
Trying XX.XXX.XXX.XXX...
telnet: connect to address XX.XXX.XXX.XXX: Connection refused
telnet: Unable to connect to remote host
Can someone please tell me what I need to fix to enable https on this EC2 instance?
Change your listen(8080) to listen(443) unless you have a web server listening on 443 and sending request to node on 8080.

Resources