From 913a49af08cde419082706fe29ba2d0d68c4488b Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Fri, 6 Dec 2024 15:12:03 -0700 Subject: [PATCH] Only overwrite servername in tls connect when host is not an IP address (#354) --- .changeset/lovely-boxes-heal.md | 7 +++++ packages/https-proxy-agent/src/index.ts | 34 ++++++++++++++++++------- packages/pac-proxy-agent/src/index.ts | 23 +++++++++++++---- packages/socks-proxy-agent/src/index.ts | 30 ++++++++++++++++++---- 4 files changed, 75 insertions(+), 19 deletions(-) create mode 100644 .changeset/lovely-boxes-heal.md diff --git a/.changeset/lovely-boxes-heal.md b/.changeset/lovely-boxes-heal.md new file mode 100644 index 00000000..b6745ca7 --- /dev/null +++ b/.changeset/lovely-boxes-heal.md @@ -0,0 +1,7 @@ +--- +"https-proxy-agent": patch +"pac-proxy-agent": patch +"socks-proxy-agent": patch +--- + +Only overwrite servername in tls connect when host is not an IP address diff --git a/packages/https-proxy-agent/src/index.ts b/packages/https-proxy-agent/src/index.ts index 272f7790..30cb5f2c 100644 --- a/packages/https-proxy-agent/src/index.ts +++ b/packages/https-proxy-agent/src/index.ts @@ -10,6 +10,24 @@ import type { OutgoingHttpHeaders } from 'http'; const debug = createDebug('https-proxy-agent'); +const setServernameFromNonIpHost = < + T extends { host?: string; servername?: string } +>( + options: T +) => { + if ( + options.servername === undefined && + options.host && + !net.isIP(options.host) + ) { + return { + ...options, + servername: options.host, + }; + } + return options; +}; + // eslint-disable-next-line @typescript-eslint/no-unused-vars type Protocol = T extends `${infer Protocol}:${infer _}` ? Protocol : never; @@ -92,12 +110,7 @@ export class HttpsProxyAgent extends Agent { let socket: net.Socket; if (proxy.protocol === 'https:') { debug('Creating `tls.Socket`: %o', this.connectOpts); - const servername = - this.connectOpts.servername || this.connectOpts.host; - socket = tls.connect({ - ...this.connectOpts, - servername, - }); + socket = tls.connect(setServernameFromNonIpHost(this.connectOpts)); } else { debug('Creating `net.Socket`: %o', this.connectOpts); socket = net.connect(this.connectOpts); @@ -146,11 +159,14 @@ export class HttpsProxyAgent extends Agent { // The proxy is connecting to a TLS server, so upgrade // this socket connection to a TLS connection. debug('Upgrading socket connection to TLS'); - const servername = opts.servername || opts.host; return tls.connect({ - ...omit(opts, 'host', 'path', 'port'), + ...omit( + setServernameFromNonIpHost(opts), + 'host', + 'path', + 'port' + ), socket, - servername, }); } diff --git a/packages/pac-proxy-agent/src/index.ts b/packages/pac-proxy-agent/src/index.ts index 585249ff..a8e61f5b 100644 --- a/packages/pac-proxy-agent/src/index.ts +++ b/packages/pac-proxy-agent/src/index.ts @@ -24,6 +24,23 @@ import { getQuickJS } from '@tootallnate/quickjs-emscripten'; const debug = createDebug('pac-proxy-agent'); +const setServernameFromNonIpHost = < + T extends { host?: string; servername?: string } +>( + options: T +) => { + if ( + options.servername === undefined && + options.host && + !net.isIP(options.host) + ) { + return { + ...options, + servername: options.host, + }; + } + return options; +}; type Protocols = keyof typeof gProtocols; // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -238,11 +255,7 @@ export class PacProxyAgent extends Agent { if (type === 'DIRECT') { // Direct connection to the destination endpoint if (secureEndpoint) { - const servername = opts.servername || opts.host; - socket = tls.connect({ - ...opts, - servername, - }); + socket = tls.connect(setServernameFromNonIpHost(opts)); } else { socket = net.connect(opts); } diff --git a/packages/socks-proxy-agent/src/index.ts b/packages/socks-proxy-agent/src/index.ts index 7a911d20..2046eb8b 100644 --- a/packages/socks-proxy-agent/src/index.ts +++ b/packages/socks-proxy-agent/src/index.ts @@ -9,6 +9,24 @@ import { URL } from 'url'; const debug = createDebug('socks-proxy-agent'); +const setServernameFromNonIpHost = < + T extends { host?: string; servername?: string } +>( + options: T +) => { + if ( + options.servername === undefined && + options.host && + !net.isIP(options.host) + ) { + return { + ...options, + servername: options.host, + }; + } + return options; +}; + function parseSocksURL(url: URL): { lookup: boolean; proxy: SocksProxy } { let lookup = false; let type: SocksProxy['type'] = 5; @@ -79,8 +97,7 @@ export type SocksProxyAgentOptions = Omit< 'ipaddress' | 'host' | 'port' | 'type' | 'userId' | 'password' > & { socketOptions?: SocksSocketOptions; -} & - http.AgentOptions; +} & http.AgentOptions; export class SocksProxyAgent extends Agent { static protocols = [ @@ -171,11 +188,14 @@ export class SocksProxyAgent extends Agent { // The proxy is connecting to a TLS server, so upgrade // this socket connection to a TLS connection. debug('Upgrading socket connection to TLS'); - const servername = opts.servername || opts.host; const tlsSocket = tls.connect({ - ...omit(opts, 'host', 'path', 'port'), + ...omit( + setServernameFromNonIpHost(opts), + 'host', + 'path', + 'port' + ), socket, - servername, }); tlsSocket.once('error', (error) => {