node-ldapjs
node-ldapjs copied to clipboard
Handling econnreset on TLS connections
I have an environment where networking gear in between my client and the LDAP server routinely issues connection resets. I am attempting to gracefully handle them without the client crashing. I have code similar to the following to intercept the errors (actual logic of the error handling excluded):
client = ldap.createClient(options);
client.on('error', function(err) {
console.dir(err);
})
This seems to handle unencrypted connections fine. I see log entries similar to the following:
[[14:57:00.486]] [DIR] Error: read ECONNRESET
at TCP.onStreamRead (internal/stream_base_commons.js:201:27) {
errno: -104,
code: 'ECONNRESET',
syscall: 'read'
}
And, after my error handling, the code resumes as normal. However, on encrypted connections, I see log entries similar to the following:
[[13:14:31.788]] [DIR] Error: read ECONNRESET
at TLSWrap.onStreamRead (internal/stream_base_commons.js:201:27) {
errno: -104,
code: 'ECONNRESET',
syscall: 'read'
}
and then my application exits. Is there some difference between TLSWrap.onStreamRead and TCP.onStreamRead that would cause the client.on to not intercept the error?
What you have written looks to me like the error is being handled. You could supply a logger set trace level output to get some better insight.
This might be related -- https://github.com/fastify/fastify/issues/2253
I am running a forked version of promised-ldap, patched to use my error handling. You can find it here:
https://github.com/worldwidewoogie/promised-ldap/blob/master/index.js
Here is the source of my test script:
require('console-stamp')(console, '[HH:MM:ss.l]')
const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
async function doit() {
while (true) {
await sleep(500)
console.dir('.')
try {
let ldap = require('promised-ldap')
let ldapClient = new ldap({
url: 'ldaps://ldap.example.com:636'
})
await ldapClient.bind('uid=a,dc=example,dc=com', 'x')
}
catch (e) {
//console.dir('.')
if (!e.lde_message || e.lde_message != 'Invalid Credentials') {
console.dir(e)
}
}
}
}
doit()
The script intentionally provides invalid credentials for the user. Here is the end of the output:
[[09:14:52.732]] [DIR] '.' [[09:14:53.531]] [DIR] '.' [[09:14:54.155]] [DIR] '.' [[09:14:54.782]] [DIR] '.' [[09:15:05.487]] [DIR] Error: read ECONNRESET at TLSWrap.onStreamRead (internal/stream_base_commons.js:201:27) { errno: -104, code: 'ECONNRESET', syscall: 'read' }
After that, the test script does not exit, but it sends no further output. If I change to non-TLS connection, I see the following:
[[10:03:27.077]] [DIR] '.' [[10:03:27.634]] [DIR] '.' [[10:03:28.325]] [DIR] '.' [[10:03:28.935]] [DIR] '.' [[10:03:29.484]] [DIR] '.' [[10:03:29.539]] [DIR] Error: read ECONNRESET at TCP.onStreamRead (internal/stream_base_commons.js:201:27) { errno: -104, code: 'ECONNRESET', syscall: 'read' } [[10:03:29.542]] [DIR] ConnectionError: 20__ldap://ldap.example.com:3890 closed at /home/woogie/src/iam/IAM-APIs/node_modules/ldapjs/lib/client/client.js:1277:17 at Array.forEach () at Client._onClose (/home/woogie/src/iam/IAM-APIs/node_modules/ldapjs/lib/client/client.js:1272:19) at Object.onceWrapper (events.js:300:26) at Socket.emit (events.js:210:5) at TCP. (net.js:659:12) { lde_message: '20__ldap://ldap.example.com:3890 closed', lde_dn: null }
...a bunch of connection reset errors elided...
[[10:04:17.504]] [DIR] '.' [[10:04:17.566]] [DIR] Error: read ECONNRESET at TCP.onStreamRead (internal/stream_base_commons.js:201:27) { errno: -104, code: 'ECONNRESET', syscall: 'read' } [[10:04:17.568]] [DIR] ConnectionError: 102__ldap://ldap.example.com:3890 closed at /home/woogie/src/iam/IAM-APIs/node_modules/ldapjs/lib/client/client.js:1277:17 at Array.forEach () at Client._onClose (/home/woogie/src/iam/IAM-APIs/node_modules/ldapjs/lib/client/client.js:1272:19) at Object.onceWrapper (events.js:300:26) at Socket.emit (events.js:210:5) at TCP. (net.js:659:12) { lde_message: '102__ldap://ldap.example.com:3890 closed', lde_dn: null } [[10:04:18.070]] [DIR] '.' [[10:04:18.819]] [DIR] '.' [[10:04:19.399]] [DIR] '.' [[10:04:19.966]] [DIR] '.' [[10:04:20.518]] [DIR] '.'
The script continues to execute until another cluster of resets occurs.
👋
On February 22, 2023, we released version 3 of this library. As a result, we are closing this issue/pull request.
Please see issue #839 for more information, including how to proceed if you feel this closure is in error.