Skip to content

Commit f1efe6d

Browse files
cjihrigtargos
authored andcommitted
tls,cli: add --trace-tls command-line flag
This commit adds a --trace-tls command-line flag. The purpose is to enable tracing of TLS connections without the need to modify existing application code. PR-URL: #27497 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 84a2768 commit f1efe6d

File tree

6 files changed

+89
-2
lines changed

6 files changed

+89
-2
lines changed

doc/api/cli.md

+9
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,14 @@ added: v2.1.0
632632
Prints a stack trace whenever synchronous I/O is detected after the first turn
633633
of the event loop.
634634

635+
### `--trace-tls`
636+
<!-- YAML
637+
added: REPLACEME
638+
-->
639+
640+
Prints TLS packet trace information to `stderr`. This can be used to debug TLS
641+
connection problems.
642+
635643
### `--trace-warnings`
636644
<!-- YAML
637645
added: v6.0.0
@@ -889,6 +897,7 @@ Node.js options that are allowed are:
889897
- `--trace-event-file-pattern`
890898
- `--trace-events-enabled`
891899
- `--trace-sync-io`
900+
- `--trace-tls`
892901
- `--trace-warnings`
893902
- `--track-heap-objects`
894903
- `--unhandled-rejections`

doc/node.1

+3
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,9 @@ Enable the collection of trace event tracing information.
302302
.It Fl -trace-sync-io
303303
Print a stack trace whenever synchronous I/O is detected after the first turn of the event loop.
304304
.
305+
.It Fl -trace-tls
306+
Prints TLS packet trace information to stderr.
307+
.
305308
.It Fl -trace-warnings
306309
Print stack traces for process warnings (including deprecations).
307310
.

lib/_tls_wrap.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ const {
5656
ERR_TLS_SESSION_ATTACK,
5757
ERR_TLS_SNI_FROM_SERVER
5858
} = require('internal/errors').codes;
59+
const { getOptionValue } = require('internal/options');
5960
const { validateString } = require('internal/validators');
61+
const traceTls = getOptionValue('--trace-tls');
6062
const kConnectOptions = Symbol('connect-options');
6163
const kDisableRenegotiation = Symbol('disable-renegotiation');
6264
const kErrorEmitted = Symbol('error-emitted');
@@ -68,6 +70,7 @@ const kEnableTrace = Symbol('enableTrace');
6870
const noop = () => {};
6971

7072
let ipServernameWarned = false;
73+
let tlsTracingWarned = false;
7174

7275
// Server side times how long a handshake is taking to protect against slow
7376
// handshakes being used for DoS.
@@ -343,9 +346,17 @@ function initRead(tlsSocket, socket) {
343346

344347
function TLSSocket(socket, opts) {
345348
const tlsOptions = { ...opts };
346-
const enableTrace = tlsOptions.enableTrace;
349+
let enableTrace = tlsOptions.enableTrace;
347350

348-
if (typeof enableTrace !== 'boolean' && enableTrace != null) {
351+
if (enableTrace == null) {
352+
enableTrace = traceTls;
353+
354+
if (enableTrace && !tlsTracingWarned) {
355+
tlsTracingWarned = true;
356+
process.emitWarning('Enabling --trace-tls can expose sensitive data in ' +
357+
'the resulting log.');
358+
}
359+
} else if (typeof enableTrace !== 'boolean') {
349360
throw new ERR_INVALID_ARG_TYPE(
350361
'options.enableTrace', 'boolean', enableTrace);
351362
}

src/node_options.cc

+4
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
373373
"first tick",
374374
&EnvironmentOptions::trace_sync_io,
375375
kAllowedInEnvironment);
376+
AddOption("--trace-tls",
377+
"prints TLS packet trace information to stderr",
378+
&EnvironmentOptions::trace_tls,
379+
kAllowedInEnvironment);
376380
AddOption("--trace-warnings",
377381
"show stack traces on process warnings",
378382
&EnvironmentOptions::trace_warnings,

src/node_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class EnvironmentOptions : public Options {
118118
bool throw_deprecation = false;
119119
bool trace_deprecation = false;
120120
bool trace_sync_io = false;
121+
bool trace_tls = false;
121122
bool trace_warnings = false;
122123
std::string unhandled_rejections;
123124
std::string userland_loader;
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
const common = require('../common');
4+
if (!common.hasCrypto) common.skip('missing crypto');
5+
const fixtures = require('../common/fixtures');
6+
7+
// Test --trace-tls CLI flag.
8+
9+
const assert = require('assert');
10+
const { fork } = require('child_process');
11+
12+
if (process.argv[2] === 'test')
13+
return test();
14+
15+
const binding = require('internal/test/binding').internalBinding;
16+
17+
if (!binding('tls_wrap').HAVE_SSL_TRACE)
18+
return common.skip('no SSL_trace() compiled into openssl');
19+
20+
const child = fork(__filename, ['test'], {
21+
silent: true,
22+
execArgv: ['--trace-tls']
23+
});
24+
25+
let stderr = '';
26+
child.stderr.setEncoding('utf8');
27+
child.stderr.on('data', (data) => stderr += data);
28+
child.on('close', common.mustCall(() => {
29+
assert(/Warning: Enabling --trace-tls can expose sensitive/.test(stderr));
30+
assert(/Received Record/.test(stderr));
31+
assert(/ClientHello/.test(stderr));
32+
}));
33+
34+
// For debugging and observation of actual trace output.
35+
child.stderr.pipe(process.stderr);
36+
child.stdout.pipe(process.stdout);
37+
38+
child.on('exit', common.mustCall((code) => {
39+
assert.strictEqual(code, 0);
40+
}));
41+
42+
function test() {
43+
const {
44+
connect, keys
45+
} = require(fixtures.path('tls-connect'));
46+
47+
connect({
48+
client: {
49+
checkServerIdentity: (servername, cert) => { },
50+
ca: `${keys.agent1.cert}\n${keys.agent6.ca}`,
51+
},
52+
server: {
53+
cert: keys.agent6.cert,
54+
key: keys.agent6.key
55+
},
56+
}, common.mustCall((err, pair, cleanup) => {
57+
return cleanup();
58+
}));
59+
}

0 commit comments

Comments
 (0)