Using Node.js with TLS getting HTTP hostname wrong error - node.js

I'm trying to write a simple Node.js server applicationthat will accept client requests, and allowing me to change the TLS/SSL protocol to use. It works fine with a browser (Firefox).
However, when I call the Node.js server from WebSphere Liberty Profile, no matter which TLS/SSL protocol I try to use, I am getting the very confusing error message:
[ERROR ] IOException invoking https://dlwester:32080/W3CookieServiceEmulator/workplace/services/w3cookie/callback/auth_data: HTTPS hostname wrong: should be <dlwester>
As you can see, it's telling me I'm using the wrong hostname, but the hostname it's telling me I should be using is what I'm already using. I've even tried using port 443, so that I don't need to specify a port, but it still gives me the same error message.
I'm not sure if the error is with Node.js or my WLP code (using JAX-RS client). I've not found a way in Node.js to bypass verifying the hostname.
var options = {
key: 'my.key',
cert: 'my.cert',
ciphers: 'TLSv1.2,TLSv1.1,TLSv1.0,SSLv3',
honorCipherOrder: true,
rejectUnauthorized: false
}
server = https.createServer(options, requestListener);
So I guess that's my first question - can I bypass hostname verification?
Has anyone else run into this error, and know a way to get around it?

This is the client verifying the hostname, not the server. You never mentioned the hostname used in your certificate -- if it doesn't match the hostname you use to address it from the client: fix the certificate.

Related

Added SSL to client side server but still not performing handshake with backend server nodejs

I am trying to implement SSL on my nodejs project. Currently, my servers are split between a client side server running on localhost port 443 and a backend server running on localhost port 5000. I have already added a self-signed SSL certificate by openSSL to my client side server as shown below.
Now here's my issue. When I send a post request to login, from what I understand, a handshake is suppose to happen between the server and the client to make a secure connection. However, that's not the case. When I used Wireshark the intercept the packets, there is no handshake happening in the process.
I am currently not sure on how to proceed because I have limited knowledge on this kind of security topics. Do I need to sign a new key and cert and add it to my backend server? Or am I doing everything wrong? If so, can I get a source or guide on how to properly create one for a nodejs server?
you have many options here for securing your backend server :
first, you can use Nginx reverse proxy server and you can add ssl/tls logic to it. nginx will handle this stuff for you.
second, you can use [https][1] package directly and pass your SSL certificate and key to it :
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
remember that the domain name your are trying to access must be set in your host ip.
[1]: https://nodejs.org/api/https.html

stompit is nodejs module failed to connect with error ""Unable to verify the first certificate"

I am using stompit module to connect to AMQ. If I set ssl as true then it is failing with error "Unable to verify the first certificate".
It works if I set rejectUnauthorized as false but then code doesn't read any message from AMQ it just connects.
I tried to use certificate by setting below properties but getting same error.
ssl: true,
key:fs.readFileSync('path'),
cert:fs.readFileSync('path'),
ca: [fs.readFileSync('path')],
If your TLS (SSL) connection to AMQ is through a reverse-proxy, such as Traefik, make sure you pass the servername property in options. This ensure the reverse-proxy presents the correct certificate according to the servername you are attempting to access.
From Stompi's connect function's code listings we can see that the NodeJS TLS module is used:
if ('ssl' in options) {
if (typeof options.ssl === 'boolean') {
if (options.ssl === true) {
transportConnect = tls.connect;
}
}
The options object you pass to Stompi's connect function will be passed through to tls.connect. Node's documentation for tls.connect mentions use of servername to ensure SNI is enabled:
Unlike the https API, tls.connect() does not enable the SNI (Server
Name Indication) extension by default, which may cause some servers to
return an incorrect certificate or reject the connection altogether.
To enable SNI, set the servername option in addition to host.

Host: localhost. is not in the cert's altnames

I'm getting the below error while doing server-side rendering.
RENDERING ERROR: { [Error: Network error: request to https://api-dev.xyz.io/graphql failed, reason: Hostname/IP doesn't match certificate's altnames: "Host: localhost. is not in the cert's altnames: DNS:*.xyz.io"]
graphQLErrors: null,
networkError:
{ [FetchError: request to https://api-dev.xyz.io/graphql failed, reason: Hostname/IP doesn't match certificate's altnames: "Host: localhost. is not in the cert's altnames: DNS:*.xyz.io"]
name: 'FetchError',
message: 'request to https://api-dev.xyz.io/graphql failed, reason: Hostname/IP doesn\'t match certificate\'s altnames: "Host: localhost. is not in the cert\'s altnames: DNS:*.xyz.io"',
type: 'system',
errno: undefined,
code: undefined },
message: 'Network error: request to https://api-dev.xyz.io/graphql failed, reason: Hostname/IP doesn\'t match certificate\'s altnames: "Host: localhost. is not in the cert\'s altnames: DNS:*.xyz.io"',
extraInfo: undefined }
Note:- I'm using react, redux, apollo-client(GraphQL) and ExpressJS(NodeJS). The API server to which I'm making the request is on another domain and I can't make any change on that.
While working with client-side rendering I'm not facing any difficulties everything is working as intended but while doing server-side render I'm getting the above error.
So I tried the below approaches on my server but still no luck.
Adding self-signed certificate
Adding 'rejectUnauthorized':false in https options.
const options = {
'key': key,
'cert': cert,
'ca': [ fs.readFileSync('local-certificate.pem') ],
'rejectUnauthorized':false
};
https.createServer(options, app).listen(httpsPort, '0.0.0.0', function onStart(err) {
if (err) { console.log(err); }
console.info('==> Listening on httpsPort %s. Open up http://0.0.0.0:%s/ in your browser.', httpsPort, options);
});
Also I tried to add an alt name in my self-signed certificate with the help of How can I generate a self-signed certificate with SubjectAltName using OpenSSL?
Is there any way to bypass certificate verification so that my express server can make a request to the API server which is on another domain with a valid certificate?
I'm still a bit unsure whether I can fix it by making any changes at my end (on my express server).
Please let me know any insights on this.
The error is not caused by the code you have in your question.
What you are doing is that you are creating a new HTTP server, that will listen to httpsPort and will bind to 0.0.0.0 which means all local IP addresses.
I suggest you omit 0.0.0.0 when binding to all local IP addresses since this is the default behavior anyway, but this is not a problem.
Then you are assigning this server the certificate local-certificate.pem which means that clients connecting to this server will be presented this certificate.
You are not connecting to any external APIs in this part of the code.
I believe Michael Landis was trying to get this point across, but didn't quite provide the solution. If your service is running on locally on 192.168.100.100, then this needs to be in your hosts file (e.g. /etc/hosts on linux):
192.168.100.100 api-dev.xyz.io
The request that's currently failing needs to be made to api-dev.xyz.io, even during SSR. It's much easier to avoid the requests to "http[s]://localhost/...".
The error message is stating that the server at https://api-dev.xyz.io/graphql believes that the incoming request is being directed to https://localhost/graphql. Therefore, it is failing because the SSL certificate is not securing https://localhost/.
Could your server-side rendering be trying to perform a fetch/API call to the same server that is doing the server-side rendering to load initial data for the render? If so, could the initial data that the client needs from the API be passed to the server-side rendering directly instead of React trying to perform an API call to itself in the server-side render?
Perhaps this tutorial could be used as an example reference.
The host name is a system-level setting below NodeJS. You'll need to have access to the the box/VM your copy of NodeJS is running on.

nodejs with ssl (https to https) Error: unable to verify the first certificate

i have two projects in the same server, 1st:
php with nginx in port 443, thats an api rest.
2nd: nodejs in port 80 this is a consuming of rest api.
1st and 2nd works alone fine and both have a ssl certificate but when i try to access api from node js to api returns exception
Error: unable to verify the first certificate
if both applications use "http" works fine, and node can access to api rest. to consume api rest in node i use "node-rest-client" i try use this args but doesn't work:
connection:{
secureOptions: constants.SSL_OP_NO_TLSv1_2,
ciphers: 'ECDHE-RSA-AES256-SHA:AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM',
honorCipherOrder: true
}
Does anyone know why this happens?

HTTPS proxy with a self-signed certificate in Node.JS

I'm trying to create a HTTPS proxy server in Node.JS v0.10.24 using a self-signed certificate. Here's the code I'm using:
var https = require('https');
var server = https.createServer({
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
});
server.on('request', function(req, res) {
res.end('hello');
});
server.listen(8080);
This server correctly boots up and is accessible via https://localhost:8080. However, when I set it as a HTTPS proxy (on Mac OS X), the server emits connection events but never emits either request or error, thus causing the connection to hang indefinitely and eventually time out.
I encountered the same issue on my Macbook. The issue appears to be that the proxy server option in OSX is using the HTTP CONNECT method to tunnel HTTPS requests.
In short, this means that you need make your server a http.Server instance and handle the connect event, which will involve forwarding TCP socket traffic.
I know this reply is a bit late, but I wrote my own HTTP/S proxy server that you can look at for reference: https://github.com/robu3/purokishi. The specific section covering the connect method is here.

Resources