diff --git a/src/rules/passthrough-handling.ts b/src/rules/passthrough-handling.ts index a13bcb685..3fdd8be58 100644 --- a/src/rules/passthrough-handling.ts +++ b/src/rules/passthrough-handling.ts @@ -24,12 +24,13 @@ import { // issues so far as possible, by closely emulating a Firefox Client Hello: const NEW_CURVES_SUPPORTED = areFFDHECurvesSupported(process.versions.openssl); +const SSL_OP_LEGACY_SERVER_CONNECT = 1 << 2; const SSL_OP_TLSEXT_PADDING = 1 << 4; const SSL_OP_NO_ENCRYPT_THEN_MAC = 1 << 19; // All settings are designed to exactly match Firefox v103, since that's a good baseline // that seems to be widely accepted and is easy to emulate from Node.js. -export const UPSTREAM_TLS_OPTIONS: tls.SecureContextOptions = { +export const getUpstreamTlsOptions = (strictChecks: boolean): tls.SecureContextOptions => ({ ecdhCurve: [ 'X25519', 'prime256v1', // N.B. Equivalent to secp256r1 @@ -74,12 +75,20 @@ export const UPSTREAM_TLS_OPTIONS: tls.SecureContextOptions = { 'AES128-SHA', 'AES256-SHA' ].join(':'), - secureOptions: SSL_OP_TLSEXT_PADDING | SSL_OP_NO_ENCRYPT_THEN_MAC, + secureOptions: strictChecks + ? SSL_OP_TLSEXT_PADDING | SSL_OP_NO_ENCRYPT_THEN_MAC + : SSL_OP_TLSEXT_PADDING | SSL_OP_NO_ENCRYPT_THEN_MAC | SSL_OP_LEGACY_SERVER_CONNECT, ...({ // Valid, but not included in Node.js TLS module types: requestOSCP: true - } as any) -}; + } as any), + + // Allow TLSv1, if !strict: + minVersion: strictChecks ? tls.DEFAULT_MIN_VERSION : 'TLSv1', + + // Skip certificate validation entirely, if not strict: + rejectUnauthorized: strictChecks, +}); // --- Various helpers for deriving parts of request/response data given partial overrides: --- diff --git a/src/rules/requests/request-handlers.ts b/src/rules/requests/request-handlers.ts index 4160b8a0b..ec2e7367f 100644 --- a/src/rules/requests/request-handlers.ts +++ b/src/rules/requests/request-handlers.ts @@ -75,7 +75,7 @@ import { getH2HeadersAfterModification, OVERRIDABLE_REQUEST_PSEUDOHEADERS, buildOverriddenBody, - UPSTREAM_TLS_OPTIONS, + getUpstreamTlsOptions, shouldUseStrictHttps, getClientRelativeHostname, getDnsLookupFunction @@ -746,10 +746,7 @@ export class PassThroughHandler extends PassThroughHandlerDefinition { agent, // TLS options: - ...UPSTREAM_TLS_OPTIONS, - // Allow TLSv1, if !strict - minVersion: strictHttpsChecks ? tls.DEFAULT_MIN_VERSION : 'TLSv1', - rejectUnauthorized: strictHttpsChecks, + ...getUpstreamTlsOptions(strictHttpsChecks), ...clientCert, ...caConfig }, (serverRes) => (async () => { diff --git a/src/rules/websockets/websocket-handlers.ts b/src/rules/websockets/websocket-handlers.ts index 41108a6c2..973ce184a 100644 --- a/src/rules/websockets/websocket-handlers.ts +++ b/src/rules/websockets/websocket-handlers.ts @@ -37,7 +37,7 @@ import { getAgent } from '../http-agents'; import { ProxySettingSource } from '../proxy-config'; import { assertParamDereferenced, RuleParameters } from '../rule-parameters'; import { - UPSTREAM_TLS_OPTIONS, + getUpstreamTlsOptions, getClientRelativeHostname, getDnsLookupFunction, shouldUseStrictHttps @@ -375,10 +375,7 @@ export class PassThroughWebSocketHandler extends PassThroughWebSocketHandlerDefi ) as { [key: string]: string }, // Simplify to string - doesn't matter though, only used by http module anyway // TLS options: - ...UPSTREAM_TLS_OPTIONS, - // Allow TLSv1, if !strict: - minVersion: strictHttpsChecks ? tls.DEFAULT_MIN_VERSION : 'TLSv1', - rejectUnauthorized: strictHttpsChecks, + ...getUpstreamTlsOptions(strictHttpsChecks), ...clientCert, ...caConfig } as WebSocket.ClientOptions & { lookup: any, maxPayload: number });