Node httpAgent with proxy and certificates (https-proxy-agent with TLS) - node.js

So I'm trying to make a call inside my node test (AVA) that uses proxy and TLS authorization.
I'm using:
typescript: 3.9.3
ts-node: 8.10.2
axios: 0.21.1
https-proxy-agent: 5.0.0
What I've learnt so far:
AxiosProxyConfig is broken at the moment so I cannot use it:
Axios proxy is not working,
https-proxy-agent is indeed working as it was said by kraiz in bug thread, but... I cannot see anything about ca, cert and key I cannot provide those I was not able to find any docs except this one https-proxy-agent npm page.
So just to wrap up with some code, that's what I'm trying to do and I have no idea how to achieve that:
const httpsProxyAgent = new HttpsProxyAgent({
cert: this.cert,
key: this.key,
ca: this.ca,
host: PROXY_HOST,
port: PROXY_PORT,
});
// then later
const config: AxiosRequestConfig = {
httpsAgent: httpsProxyAgent,
headers: { ... }
proxy: false
};
Though HttpsProxyAgent seems to extend Agent those options (certs part) are not used and I get UNABLE_TO_VERIFY_LEAF_SIGNATURE error that indicates that ca is ignored.
Does anyone knows how to provide those certs to this agent?
I couldn't find any answers. I'm not a node expert so I might have missed something obvious.
Thanks in advance!
PS. I've also tried Objects.assign() like this
// this proxy agent is working for sure (tested)
const httpsProxyAgent = new HttpsProxyAgent('http://proxy:1234');
// trying to assign certs after creating httpsProxyAgent
Object.assign(httpsAgent.options, {
ca: this.ca,
key: this.key,
cert: this.cert
});
// then again passing it to AxiosRequestConfig.httpAgent and making a call
result was once again UNABLE_TO_VERIFY_LEAF_SIGNATURE.
PSS. I've seen this better-https-proxy-agent (git page) that seems to have solution, the only drawback is I cannot see any TS support.

Related

How get client certification info when using Hapi?

I am using the Hapi framawork in my node.js project and I'd like to get the client certificate info.
I have searched the internet looking for this info but with no luck so far.
Either I am doing a bad search or there's not an easy way to do it.
Anyways I believe that must be a way to do so.
Does anyone know how to get cert's subject, fingerprint, and etc. while using Hapi?
const tls = {
key: fs.readFileSync('../certs/xyz.key'),
cert: fs.readFileSync('../certs/xyz.crt'),
passphrase: 'xxxxxxxxxx',
ca: fs.readFileSync('../certs/rootCA.crt'),
// should request the client cert
requestCert: true,
rejectUnauthorized: true
};
console.log(req.socket.getPeerCertificate()); /* doesn't work */

How to log SSL handshake in node's https module

I have a server written in node which implements a secure two-way SSL web-server:
var https = require('https');
var express = require('express');
var app = express();
var options {
key: ...,
cert: ...,
ca: ...,
requestCert: true,
rejectUnauthorized: true
};
https.createServer(options, app).listen(port, host);
But for some unknown reason, the client fails to connect. So it would be great if I could get any logs on why the connection has failed.
So far, all the logs I can get come from app which is an express object. But the problem is that when a connection is rejected due to a certificate issues, it does not reach express so I get no error logs. How can I get logs from https server?
I've run into this problem as well and while I couldn't come up with a solution that logs all the errors within the https module, I was able to get it to log debug information by using:
NODE_DEBUG='tls,https' node server.js
This isn't ideal as it doesn't give you the exact error (eg: Bad SSL Handshake) and the related traceback, it does give you information like TLS: onhandshakestart which lets you figure out if there was an error if you can't find a corresponding TLS: onhandshakeend in the logs.
There is an option in the config for createServer called enableTrace that causes Node to print a ton of details about the handshake:
var options {
key: ...,
cert: ...,
ca: ...,
requestCert: true,
rejectUnauthorized: true,
enableTrace: true // Set this :)
};
See the docs for more info.

How to create a SSL SOAP Client in Nodejs

First of all, I'd like to make it clear this is my very first time dealing with certificates/keys/pfx/etc.. so please correct me if I'm wrong :)
I'm using node-soap to create a client to a web-server and consume its' WSDL. Doing so only on HTTP protocol and not HTTPS i had success and everything worked just fine, but now with the pfx I get the mac verify failure error.
the relevant code:
import * as soap from 'soap';
import * as fs from 'fs';
let client_options: {
forceSoap12Headers: true,
wsdl_options:{
pfx: fs.readFileSync('PATH\TO\MY\PFX')
}
};
soap.createClient('HTTPS\WEB-SERVER\URL?wsdl', client_options, (error, client)=>{
console.log(error.message) // <-- mac verify failure
console.log(client) // <-- undefined
});
Worth noting:
I could not find any documentation of the node-soap library for the -- wsdl_options property, the pfx one i accidently found while googling so i dont know any other options available.
Trying to deal with this error, i found that an option of passphrase: 'password' should be added to options BUT for options of createServer with the https library, not for creating a client with node-soap.. relevant links: stackoverflow question , git issue
I've been dealing with this for the past 3 days, got to debugging all node-soap, https, and request libraries.. got lost in there.
Any help or suggestions would be much appreciated, thanks in advance!
did you see this link in github? https://github.com/nodejs/node-v0.x-archive/issues/7407 it also says set passphrase: 'password' in this case

Self signed cert NodeJS rejectUnauthorized

I created a structure certificates to authenticate client-> server, allowing only certificates recognized by the CA using this step by step: https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html
I checked the authority with openssl, and it returns to me OK the certificate server and client, with the same CA. But by setting the parameter rejectUnauthorized to true on the server, the client can not connect.
Is there any extra parameter should I set up to allow authentication by a certificate that I generated?
---- Edit
On the client side I get the following error: ""ECONNRESET" socket hang up"
I spent a long time digging into a similar issue, and I wrote up this to talk about how to dig into various OpenSSL issues with node.js: http://www.thedreaming.org/2016/09/27/nodejs-ssl/
The short answer, though, is if you need to pass the ca parameter when creating you client connection. If you have the self-signed certificate stored in cert.pem, then the client code looks something like:
var https = require('https');
var fs = require('fs');
var certificate = fs.readFileSync('cert.pem');
var options = {
host: serverHost,
port: 443,
path: '/',
ca: [certificate]
};
https.request(options, function(res) {
res.pipe(process.stdout);
}).end();

how to configure https in sails.js

I am trying to setup a local HTTPS server for testing in Sails.js? I am not able to find any pointer how to do that in sails.js? For express,
var express = require('express');
var https = require('https');
var http = require('http');
var fs = require('fs');
// This line is from the Node.js HTTPS documentation.
var options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
// Create a service (the app object is just a callback).
var app = express();
// Create an HTTP service.
http.createServer(app).listen(80);
// Create an HTTPS service identical to the HTTP service.
https.createServer(options, app).listen(443);
Any idea about sails.js?
For sails.js version 0.10, include this in config/locals.js (if locals.js does not exist, create it):
var fs = require('fs');
module.exports = {
ssl : {
key: fs.readFileSync('path-to-key.key'),
cert: fs.readFileSync('path-to-crt.crt')
}
};
Source: https://stackoverflow.com/a/28565113/2459071
If you're using the latest v0.9 (and maybe some versions of v0.8) take look inside of config/bootstrap.js. You should be able to access your express app via the sails.express context. From there I think you should be able to do with it what you want to...
Also someone in the #sailsjs irc channel said this worked for them
module.exports.bootstrap = function (cb) {
var fs = require('fs');
sails.config.express.serverOptions = {
key: fs.readFileSync('ssl/key.pem'),
cert: fs.readFileSync('ssl/cert.pem')
};
cb();
};
Maybe it's just me but I could get either of the above working for sails v0.9.7, but I did get it working by editing the config/local.js file like so;
var fs = require('fs');
module.exports = {
port: process.env.PORT || 1337,
environment: process.env.NODE_ENV || 'development',
express: { serverOptions : {
key: fs.readFileSync('ssl/key.pem'),
cert: fs.readFileSync('ssl/cert.pem')
}
}
};
Now I'm not saying this is the 'correct' way to do this, however it works for me!
Shameless self promotion
More about this on my blog!
End shameless self promotion :D
This contribution enhances the solution for to support native mobile applications and old browsers.
This solution worked really well for me when when just using a modern web browser to access my SSL site. However when I attempted to make requests using the AFNetworking library it did not recognise the SSL certificate. This was due to the iPhone application requiring the intermediate SSL certificates (sometimes called the ca bundle).
You can add the intermediate certificate in using the following code.
express: {
serverOptions : {
key: fs.readFileSync('ssl/key.pem'),
cert: fs.readFileSync('ssl/cert.pem'),
ca: fs.readFileSync('ssl/intermediate.pem')
}
}
When creating you intermediate certificate (which can normally be downloaded from your SSL certificate provider) it is important to get the order of certificates right.
This linux command really helped with debugging.
openssl s_client -connect yoursite.com:443 -showcerts
The above does not work for sails v0.9.3. I ended up with the following workaround. (require fs first of course)
express : {serverOptions : {
key: fs.readFileSync('ssl/server-key.pem'),
cert: fs.readFileSync('ssl/server-cert.pem'),
}}
I have also faced this kind of issues in my production sails app (v0.11.x and v0.12.x). Android release version apk is not able to connect to sails app and some old version browsers do not accept SSL certificate with web app.
I got some intermediate certificate error like below
The certificate is not trusted in all web browsers. You may need to install an Intermediate/chain certificate to link it to a trusted root certificate.
Finally, I found a solution
ssl: {
ca: require('fs').readFileSync('ssl/intermediate.crt', 'utf8').toString(),
key: require('fs').readFileSync('ssl/example_com.key', 'utf8').toString(),
cert: require('fs').readFileSync('ssl/main.crt', 'utf8').toString()
}
I hope this will help someone.

Resources