Skip to content

Commit b3c05d1

Browse files
committed
extract magic number into constant and make use of cert we have
1 parent 8e35f8e commit b3c05d1

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

src/cmap/connect.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,14 @@ export async function prepareHandshakeDocument(
281281
return handshakeDoc;
282282
}
283283

284+
/**
285+
* Default TCP keepAlive initial delay in milliseconds.
286+
* Set to half the Azure load balancer idle timeout (240s) to ensure
287+
* probes fire well before cloud LBs (Azure, AWS PrivateLink/NLB)
288+
* drop idle connections.
289+
* */
290+
const DEFAULT_KEEP_ALIVE_INITIAL_DELAY_MS = 120_000;
291+
284292
/** @public */
285293
export const LEGAL_TLS_SOCKET_OPTIONS = [
286294
'allowPartialTrustChain',
@@ -324,7 +332,7 @@ function parseConnectOptions(options: ConnectionOptions): SocketConnectOpts {
324332
(result as Document)[name] = options[name];
325333
}
326334
}
327-
result.keepAliveInitialDelay ??= 120000;
335+
result.keepAliveInitialDelay ??= DEFAULT_KEEP_ALIVE_INITIAL_DELAY_MS;
328336
result.keepAlive = true;
329337
result.noDelay = options.noDelay ?? true;
330338

@@ -370,6 +378,9 @@ export async function makeSocket(options: MakeConnectionOptions): Promise<Stream
370378
const useTLS = options.tls ?? false;
371379
const connectTimeoutMS = options.connectTimeoutMS ?? 30000;
372380
const existingSocket = options.existingSocket;
381+
const keepAliveInitialDelay =
382+
options.keepAliveInitialDelay ?? DEFAULT_KEEP_ALIVE_INITIAL_DELAY_MS;
383+
const noDelay = options.noDelay ?? true;
373384

374385
let socket: Stream;
375386

@@ -396,8 +407,11 @@ export async function makeSocket(options: MakeConnectionOptions): Promise<Stream
396407
socket = net.createConnection(parseConnectOptions(options));
397408
}
398409

399-
socket.setKeepAlive(true, options.keepAliveInitialDelay ?? 120_000);
400-
socket.setNoDelay(options.noDelay ?? true);
410+
// Explicit setKeepAlive/setNoDelay are required because tls.connect() silently
411+
// ignores these constructor due to a Node.js bug.
412+
// See: https://github.com/nodejs/node/issues/62003
413+
socket.setKeepAlive(true, keepAliveInitialDelay);
414+
socket.setNoDelay(noDelay);
401415
socket.setTimeout(connectTimeoutMS);
402416

403417
let cancellationHandler: ((err: Error) => void) | null = null;

test/unit/cmap/connect.test.ts

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from 'chai';
2-
import { execSync } from 'child_process';
3-
import * as crypto from 'crypto';
2+
import * as fs from 'fs';
43
import * as net from 'net';
4+
import * as path from 'path';
55
import * as process from 'process';
66
import * as sinon from 'sinon';
77
import * as tls from 'tls';
@@ -459,24 +459,26 @@ describe('Connect Tests', function () {
459459
// TLS sockets created by tls.connect() do not honor keepAlive/noDelay constructor
460460
// options due to a Node.js bug (options are not forwarded to the net.Socket constructor).
461461
// The driver must call setKeepAlive/setNoDelay explicitly on all sockets.
462-
// See: https://github.com/nodejs/node/issues/...
462+
// See: https://github.com/nodejs/node/issues/62003
463463

464464
let tlsServer: tls.Server;
465465
let tlsPort: number;
466466
let setKeepAliveSpy: sinon.SinonSpy;
467467
let setNoDelaySpy: sinon.SinonSpy;
468468

469+
const serverPem = fs.readFileSync(
470+
path.join(__dirname, '../../integration/auth/ssl/server.pem')
471+
);
472+
469473
before(function (done) {
470-
const { privateKey } = crypto.generateKeyPairSync('rsa', { modulusLength: 2048 });
471-
const key = privateKey.export({ type: 'pkcs8', format: 'pem' });
472-
const cert = execSync(
473-
'openssl req -new -x509 -key /dev/stdin -out /dev/stdout -days 1 -subj /CN=localhost -batch 2>/dev/null',
474-
{ input: key }
475-
).toString();
476-
477-
tlsServer = tls.createServer({ key, cert }, () => {
478-
/* empty */
479-
});
474+
// @SECLEVEL=0 allows the legacy test certificate (signed with SHA-1/1024-bit RSA)
475+
// to be accepted by OpenSSL 3.x, which rejects at the default security level.
476+
tlsServer = tls.createServer(
477+
{ key: serverPem, cert: serverPem, ciphers: 'DEFAULT:@SECLEVEL=0' },
478+
() => {
479+
/* empty */
480+
}
481+
);
480482
tlsServer.listen(0, '127.0.0.1', () => {
481483
tlsPort = (tlsServer.address() as net.AddressInfo).port;
482484
done();
@@ -501,7 +503,8 @@ describe('Connect Tests', function () {
501503
const socket = await makeSocket({
502504
hostAddress: new HostAddress(`127.0.0.1:${tlsPort}`),
503505
tls: true,
504-
rejectUnauthorized: false
506+
rejectUnauthorized: false,
507+
ciphers: 'DEFAULT:@SECLEVEL=0'
505508
} as ConnectionOptions);
506509

507510
try {
@@ -516,6 +519,7 @@ describe('Connect Tests', function () {
516519
hostAddress: new HostAddress(`127.0.0.1:${tlsPort}`),
517520
tls: true,
518521
rejectUnauthorized: false,
522+
ciphers: 'DEFAULT:@SECLEVEL=0',
519523
keepAliveInitialDelay: 5000
520524
} as ConnectionOptions);
521525

@@ -530,7 +534,8 @@ describe('Connect Tests', function () {
530534
const socket = await makeSocket({
531535
hostAddress: new HostAddress(`127.0.0.1:${tlsPort}`),
532536
tls: true,
533-
rejectUnauthorized: false
537+
rejectUnauthorized: false,
538+
ciphers: 'DEFAULT:@SECLEVEL=0'
534539
} as ConnectionOptions);
535540

536541
try {

0 commit comments

Comments
 (0)