From ed64f1c5fdb2e9049cc35dfc8540cc8236b1c001 Mon Sep 17 00:00:00 2001 From: islandryu Date: Sun, 29 Dec 2024 13:41:34 +0900 Subject: [PATCH 1/4] http2: omit server name when HTTP2 host is IP address Fixes: https://github.com/nodejs/node/issues/56189 --- lib/internal/http2/core.js | 24 +++++---- test/parallel/test-http2-ip-address-host.js | 59 +++++++++++++++++++++ 2 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 test/parallel/test-http2-ip-address-host.js diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index b41e1baee24644..4f2392c9829cc3 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -636,15 +636,21 @@ function initOriginSet(session) { if (originSet === undefined) { const socket = session[kSocket]; session[kState].originSet = originSet = new SafeSet(); - if (socket.servername != null) { - let originString = `https://${socket.servername}`; - if (socket.remotePort != null) - originString += `:${socket.remotePort}`; - // We have to ensure that it is a properly serialized - // ASCII origin string. The socket.servername might not - // be properly ASCII encoded. - originSet.add(getURLOrigin(originString)); + let hostName = socket.servername; + if (hostName === null || hostName === false) { + if (socket.remoteFamily === 'IPv6') { + hostName = `[${socket.remoteAddress}]`; + } else { + hostName = socket.remoteAddress; + } } + let originString = `https://${hostName}`; + if (socket.remotePort != null) + originString += `:${socket.remotePort}`; + // We have to ensure that it is a properly serialized + // ASCII origin string. The socket.servername might not + // be properly ASCII encoded. + originSet.add(getURLOrigin(originString)); } return originSet; } @@ -3333,7 +3339,7 @@ function connect(authority, options, listener) { socket = net.connect({ port, host, ...options }); break; case 'https:': - socket = tls.connect(port, host, initializeTLSOptions(options, host)); + socket = tls.connect(port, host, initializeTLSOptions(options, net.isIP(host) ? undefined : host)); break; default: throw new ERR_HTTP2_UNSUPPORTED_PROTOCOL(protocol); diff --git a/test/parallel/test-http2-ip-address-host.js b/test/parallel/test-http2-ip-address-host.js new file mode 100644 index 00000000000000..7f6de2b34a185f --- /dev/null +++ b/test/parallel/test-http2-ip-address-host.js @@ -0,0 +1,59 @@ +'use strict'; + +const common = require('../common'); if (!common.hasCrypto) { common.skip('missing crypto'); }; +const assert = require('assert'); +const fixtures = require('../common/fixtures'); +const h2 = require('http2'); + +function loadKey(keyname) { + return fixtures.readKey(keyname, 'binary'); +} + +const key = loadKey('agent8-key.pem'); +const cert = fixtures.readKey('agent8-cert.pem'); + +const server = h2.createSecureServer({ key, cert }); +server.on('stream', common.mustCall((stream) => { + const session = stream.session; + assert.strictEqual(session.servername, undefined); + stream.respond({ 'content-type': 'application/json' }); + stream.end(JSON.stringify({ + servername: session.servername, + originSet: session.originSet + }) + ); +}, 2)); +server.on('close', common.mustCall()); +server.listen(0, common.mustCall(async () => { + await new Promise((resolve) => { + const client = h2.connect(`https://127.0.0.1:${server.address().port}`, + { rejectUnauthorized: false }); + const req = client.request(); + let data = ''; + req.setEncoding('utf8'); + req.on('data', (d) => data += d); + req.on('end', common.mustCall(() => { + const originSet = req.session.originSet; + assert.strictEqual(originSet[0], `https://127.0.0.1:${server.address().port}`); + client.close(); + resolve(); + })); + }); + + await new Promise((resolve) => { + // Test with IPv6 address + const client = h2.connect(`https://[::1]:${server.address().port}`, + { rejectUnauthorized: false }); + const req = client.request(); + let data = ''; + req.setEncoding('utf8'); + req.on('data', (d) => data += d); + req.on('end', common.mustCall(() => { + const originSet = req.session.originSet; + assert.strictEqual(originSet[0], `https://[::1]:${server.address().port}`); + client.close(); + resolve(); + })); + }); + server.close(); +})); From 46bcf780789e94f2d4dc1f75f7944ffd682b1b5e Mon Sep 17 00:00:00 2001 From: islandryu Date: Tue, 14 Jan 2025 12:43:58 +0900 Subject: [PATCH 2/4] fix test --- test/parallel/test-http2-ip-address-host.js | 37 ++++++++------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/test/parallel/test-http2-ip-address-host.js b/test/parallel/test-http2-ip-address-host.js index 7f6de2b34a185f..c5c0ff6a908eee 100644 --- a/test/parallel/test-http2-ip-address-host.js +++ b/test/parallel/test-http2-ip-address-host.js @@ -1,6 +1,7 @@ 'use strict'; -const common = require('../common'); if (!common.hasCrypto) { common.skip('missing crypto'); }; +const common = require('../common'); +if (!common.hasCrypto) { common.skip('missing crypto'); }; const assert = require('assert'); const fixtures = require('../common/fixtures'); const h2 = require('http2'); @@ -23,10 +24,12 @@ server.on('stream', common.mustCall((stream) => { }) ); }, 2)); -server.on('close', common.mustCall()); + +let done = 0; + server.listen(0, common.mustCall(async () => { - await new Promise((resolve) => { - const client = h2.connect(`https://127.0.0.1:${server.address().port}`, + function handleRequest(url) { + const client = h2.connect(url, { rejectUnauthorized: false }); const req = client.request(); let data = ''; @@ -34,26 +37,14 @@ server.listen(0, common.mustCall(async () => { req.on('data', (d) => data += d); req.on('end', common.mustCall(() => { const originSet = req.session.originSet; - assert.strictEqual(originSet[0], `https://127.0.0.1:${server.address().port}`); + assert.strictEqual(originSet[0], url); client.close(); - resolve(); + if (++done === 2) server.close(); })); - }); + } - await new Promise((resolve) => { - // Test with IPv6 address - const client = h2.connect(`https://[::1]:${server.address().port}`, - { rejectUnauthorized: false }); - const req = client.request(); - let data = ''; - req.setEncoding('utf8'); - req.on('data', (d) => data += d); - req.on('end', common.mustCall(() => { - const originSet = req.session.originSet; - assert.strictEqual(originSet[0], `https://[::1]:${server.address().port}`); - client.close(); - resolve(); - })); - }); - server.close(); + const ipv4Url = `https://127.0.0.1:${server.address().port}`; + const ipv6Url = `https://[::1]:${server.address().port}`; + handleRequest(ipv4Url); + if (common.hasIPv6) handleRequest(ipv6Url); })); From 36d945bdc1f9bef50957930b946124b004ea9c4c Mon Sep 17 00:00:00 2001 From: Shima Ryuhei <65934663+islandryu@users.noreply.github.com> Date: Tue, 14 Jan 2025 16:23:46 +0900 Subject: [PATCH 3/4] Update test/parallel/test-http2-ip-address-host.js Co-authored-by: Luigi Pinca --- test/parallel/test-http2-ip-address-host.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-http2-ip-address-host.js b/test/parallel/test-http2-ip-address-host.js index c5c0ff6a908eee..127813acded663 100644 --- a/test/parallel/test-http2-ip-address-host.js +++ b/test/parallel/test-http2-ip-address-host.js @@ -27,7 +27,7 @@ server.on('stream', common.mustCall((stream) => { let done = 0; -server.listen(0, common.mustCall(async () => { +server.listen(0, common.mustCall(() => { function handleRequest(url) { const client = h2.connect(url, { rejectUnauthorized: false }); From 72eb4dc11b295d66cf05bb36e44147d6b7785077 Mon Sep 17 00:00:00 2001 From: islandryu Date: Tue, 14 Jan 2025 21:43:36 +0900 Subject: [PATCH 4/4] fix test --- test/parallel/test-http2-ip-address-host.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/parallel/test-http2-ip-address-host.js b/test/parallel/test-http2-ip-address-host.js index 127813acded663..c0699a89169153 100644 --- a/test/parallel/test-http2-ip-address-host.js +++ b/test/parallel/test-http2-ip-address-host.js @@ -14,6 +14,9 @@ const key = loadKey('agent8-key.pem'); const cert = fixtures.readKey('agent8-cert.pem'); const server = h2.createSecureServer({ key, cert }); +const hasIPv6 = common.hasIPv6; +const testCount = hasIPv6 ? 2 : 1; + server.on('stream', common.mustCall((stream) => { const session = stream.session; assert.strictEqual(session.servername, undefined); @@ -23,7 +26,7 @@ server.on('stream', common.mustCall((stream) => { originSet: session.originSet }) ); -}, 2)); +}, testCount)); let done = 0; @@ -39,12 +42,12 @@ server.listen(0, common.mustCall(() => { const originSet = req.session.originSet; assert.strictEqual(originSet[0], url); client.close(); - if (++done === 2) server.close(); + if (++done === testCount) server.close(); })); } const ipv4Url = `https://127.0.0.1:${server.address().port}`; const ipv6Url = `https://[::1]:${server.address().port}`; handleRequest(ipv4Url); - if (common.hasIPv6) handleRequest(ipv6Url); + if (hasIPv6) handleRequest(ipv6Url); }));