Allow Legacy Renegotiation for NodeJs - node.js

The best way to solve this would be to update the SSL endpoint I'm trying to connect to but I don't have the ability too.
I'm trying to reach a SOAP endpoint (it's painful) for an application that is barily being maintained and thus probably won't be able to get the proper SSL patch.
It's sitting behind a proxy that is doing active SSL rewrites and could also be to blame for the error:
var request = require("request")
var soap = require("soap")
const fs = require('fs')
var specialRequest = request.defaults({
ca: fs.readFileSync("rewrite-example.pem")
})
var options = { request: specialRequest }
const WSDL = "https://SSL-rewrite.example?wsdl"
soap.createClient(WSDL, options, function(err, client) {
if(err) throw Error(err)
})
Error:
Uncaught TypeError: req.then is not a function
at HttpClient.request (../node_modules/soap/lib/http.js:191:13)
at Object.open_wsdl (../node_modules/soap/lib/wsdl/index.js:1271:20)
at openWsdl (../node_modules/soap/lib/soap.js:70:16)
at ../node_modules/soap/lib/soap.js:48:13
at _requestWSDL (../node_modules/soap/lib/soap.js:76:9)
at Object.createClient (../node_modules/soap/lib/soap.js:94:5)
> Uncaught: Error: write EPROTO C017726B8C7F0000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:908
From what I found here, it's possible to create a custom OpenSSL config file allowing unsafe legacy renegotiation. And using Node's --openssl-config flag, it should be possible to "ignore" the renegotiation. I've tried writing a custom config file as written in the first link and passing it in but with no avail.
This question has been asked before, though reverting to an older verision of Node would not be ideal.
What might be some other wasys to resolve this?

As you already have found this error is coming from CVE-2009-3555, this is IIS issue, so it even won't be ignored using node flags. Since node 17 or 18 they removed OpenSSL option to accept legacy servers.
I thing better solution in your case is passing httpsAgent with option.
soap.js uses Axios as of v0.40.0 according to readme, so you should set request param like this:
const crypto = require('crypto')
const options = {
request: axios.create({
// axios options
httpsAgent: new https.Agent({
// for self signed you could also add
// rejectUnauthorized: false,
// allow legacy server
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
}),
}),
}
https.Agent's secureOptions is a numeric bitmask of the SSL_OP_* options.

Related

How to integrate OIDC Provider in Node jS

I tried to Integrate OIDC Provider to Node JS and I have a Sample Code. So, I run this Sample code it's throwing an error(unrecognized route or not allowed method (GET on /api/v1/.well-known/openid-configuration)).The problem is Issuer(https://localhost:3000) this Issuer is working fine. but i will change this Issuer((https://localhost:3000/api/v1/)) it's not working How to fix this Issue and I facing another issue also when I implement oldc-provider in node js. They Routes are override how to fix this issue
Sample.js
const { Provider } = require('oidc-provider');
const configuration = {
// ... see available options /docs
clients: [{
client_id: 'foo',
client_secret: 'bar',
redirect_uris: ['http://localhost:3000/api/v1/'],
true_provider: "pcc"
// + other client properties
}],
};
const oidc = new Provider('http://localhost:3000/api/v1/', configuration);
// express/nodejs style application callback (req, res, next) for use with express apps, see /examples/express.js
oidc.callback()
// or just expose a server standalone, see /examples/standalone.js
const server = oidc.listen(3000, () => {
console.log('oidc-provider listening on port 3000, check http://localhost:3000/api/v1/.well-known/openid-configuration');
});
Error
Defining Issuer Identifier with a path component does not affect anything route-wise.
You have two options, either mount the provider to a path (see docs), or define the actual paths you want for each endpoint to be prefixed (see docs).
I think you're looking for a way to mount, so the first one.

Nodejs Fetch API: unable to verify the first certificate

I'm using the fetch API module in my Philips Hue project and when I make a call to the local ip address (my hub) it produces that error in the title.
const fetch = require('node-fetch');
const gateway = "192.168.0.12";
const username = "username";
let getLights = function(){
fetch(`https://${gateway}/api/${username}/lights`, {
method: 'GET'
}).then((res) => {
return res.json();
}).then((json) => {
console.log(json);
});
}
module.exports = {getLights};
Any SECURE fix this will eventually go onto the public internet for me to access my lights from anywhere sooo?
To skip the SSL tests, you can use this:
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
It seems like you tried to access it using HTTPS. Most likely on your local network it is going to be HTTP
So by changing https://${gateway}/api/${username}/lights to http://${gateway}/api/${username}/lights should work.
If you're trying to keep it HTTPS then you will have to install a SSL certificate authority onto your network.
These may be useful sources if you're trying to get that done:
https://www.freecodecamp.org/news/how-to-get-https-working-on-your-local-development-environment-in-5-minutes-7af615770eec/
https://letsencrypt.org/docs/certificates-for-localhost/

Wrong TLS with RESTDataSource from Apollo and HttpsProxyAgent

I'm setting up a link between my Apollo Server (Node) and a REST API. My endpoint is https://app.myproject.local/api/v1 and is served via Hotel through a Pacfile available from http://localhost:2000/proxy.pac.
In reality this endpoint is also available from http://localhost:4000/api/v1 but I want to access it with Hotel.
I figured app.myproject.local wasn't resolved if I tried to access it directly in the node application, so I should go through HttpsProxyAgent and get it from there.
import { RESTDataSource } from 'apollo-datasource-rest'
import HttpsProxyAgent from 'https-proxy-agent'
import { restConfig } from '../config/restConfig'
export class RestAPI extends RESTDataSource {
constructor() {
super()
this.baseURL = restConfig.endpoint
}
public willSendRequest(request: any) {
request.agent = new HttpsProxyAgent({
host: 'localhost',
port: 2000,
secureProxy: false,
rejectUnauthorized: false,
})
}
public async test() {
return this.get('/status')
}
}
Despite having rejectUnauthorized it throws an error
(node:40593) UnhandledPromiseRejectionWarning: FetchError: request to https://app.myproject.local/api/v1/organizations/current failed, reason: write EPROTO 4474312128:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:332:
When I try to do the same kind of fetch with cURL it does work with
curl --insecure --proxy http://localhost:2000/proxy.pac https://app.myproject.local/api/v1/status
It may be a misunderstanding from my part but I thought rejectUnauthorized would bypass this SSL certificate problem. I'm actually using this in development environment so it does not matter so much, in production I won't need to go through all this.
I'm using the documentation of https://node.readthedocs.io/en/latest/api/tls/#tlsconnectport-host-options-callback to help me pass arguments to HttpsProxyAgent
const https = require('https')
...
willSendRequest(request) {
request.agent = new https.Agent({ rejectUnauthorized: false })
}
...
proxy.pac is a file that tells a web browser which proxy to use for a given request. You generally don't use it as a proxy itself.

HTTPS TLS Settings in Node

I was looking through my codebase today, the portion which sets up the server and found the following lines:
var https = require('https');
https.globalAgent.options.secureProtocol = 'TLSv1_2_method';
function createHttpsServer(app) {
var https = require('https');
var fs = require('fs');
const options = {
secureProtocol: 'TLSv1_2_method',
// ...
};
var server = https.createServer(options, app);
return server;
}
It looked like code duplication to me and I am not sure why these do different things (or do they?).
A colleague of mine told me that the top one is for controlling TLS in HTTPS requests made from NodeJS, which in turn, gives us access to the https.agent which is used for all things related to client HTTP requests.
This was also compared to the ServicePointManager in the .NET world.
So do these methods both do different things? At some point, our code does:
var server = protocol === 'https' ? createHttpsServer(app) : createHttpServer(app);
Wouldn't that be using the same server at the end of the day?
var server = protocol === 'https' ? createHttpsServer(app) : createHttpServer(app);
The above line creates the same server, the only difference is if the protocol is 'https' it will run on HTTPS server (this require SSL certificate) whereas if the protocol is http it will run on HTTP server.

AWS-SDK for node js connection management

Does aws-sdk for node js manage it's connections through an internal pool?
Their documentation kind of leads me to believe that.
httpOptions (map) — A set of options to pass to the low-level HTTP
request. Currently supported options are:
proxy [String] — the URL to proxy requests through agent [http.Agent,
https.Agent] — the Agent object to perform HTTP requests with. Used
for connection pooling. Defaults to the global agent
(http.globalAgent) for non-SSL connections. Note that for SSL
connections, a special Agent object is used in order to enable peer
certificate verification. This feature is only available in the
Node.js environment.
But there's no way, at least none that I could find, that'd let me define any connection pool properties.
What are my options if I want to control the concurrent connections in use?
Is it better to let the SDK handle that?
can give the http.Agent with whatever settings you want for max sockets.
var AWS = require('aws-sdk');
var http = require('http');
AWS.config.update({
httpOptions: {
agent: new http.Agent(...)
}
})
I have been looking into this a little bit more.
I dug around and figured out the defaults being used.
AWS-SDK is using the node http module, of which the defaultSocketCount is INFINITY.
They are using https module under the wraps with a maxSocketCount of 50.
The relevant code snippet.
sslAgent: function sslAgent() {
var https = require('https');
if (!AWS.NodeHttpClient.sslAgent) {
AWS.NodeHttpClient.sslAgent = new https.Agent({rejectUnauthorized: true});
AWS.NodeHttpClient.sslAgent.setMaxListeners(0);
// delegate maxSockets to globalAgent, set a default limit of 50 if current value is Infinity.
// Users can bypass this default by supplying their own Agent as part of SDK configuration.
Object.defineProperty(AWS.NodeHttpClient.sslAgent, 'maxSockets', {
enumerable: true,
get: function() {
var defaultMaxSockets = 50;
var globalAgent = https.globalAgent;
if (globalAgent && globalAgent.maxSockets !== Infinity && typeof globalAgent.maxSockets === 'number') {
return globalAgent.maxSockets;
}
return defaultMaxSockets;
}
});
}
return AWS.NodeHttpClient.sslAgent;
}
For manipulating the socket counts, see BretzL's answer.
There is however now way to set the agent for both http and https at once. You can work around this by updating the configuration as you switch from http to https and vice versa.
See : https://github.com/aws/aws-sdk-js/issues/1185

Resources