Przeglądaj źródła

Share TLS cache with Conduit broker and TransferURLs

Amir Khan 9 miesięcy temu
rodzic
commit
465bc5a9a0

+ 6 - 4
psiphon/controller.go

@@ -275,14 +275,14 @@ func NewController(config *Config) (controller *Controller, err error) {
 	var tacticAppliedReceivers []TacticsAppliedReceiver
 
 	isProxy := false
-	controller.inproxyClientBrokerClientManager = NewInproxyBrokerClientManager(config, isProxy)
+	controller.inproxyClientBrokerClientManager = NewInproxyBrokerClientManager(config, isProxy, controller.tlsClientSessionCache)
 	tacticAppliedReceivers = append(tacticAppliedReceivers, controller.inproxyClientBrokerClientManager)
 	controller.inproxyNATStateManager = NewInproxyNATStateManager(config)
 	tacticAppliedReceivers = append(tacticAppliedReceivers, controller.inproxyNATStateManager)
 
 	if config.InproxyEnableProxy {
 		isProxy = true
-		controller.inproxyProxyBrokerClientManager = NewInproxyBrokerClientManager(config, isProxy)
+		controller.inproxyProxyBrokerClientManager = NewInproxyBrokerClientManager(config, isProxy, controller.tlsClientSessionCache)
 		tacticAppliedReceivers = append(tacticAppliedReceivers, controller.inproxyProxyBrokerClientManager)
 	}
 
@@ -632,7 +632,8 @@ fetcherLoop:
 				controller.config,
 				attempt,
 				tunnel,
-				controller.untunneledDialConfig)
+				controller.untunneledDialConfig,
+				controller.tlsClientSessionCache)
 
 			if err == nil {
 				lastFetchTime = time.Now()
@@ -721,7 +722,8 @@ downloadLoop:
 				attempt,
 				handshakeVersion,
 				tunnel,
-				controller.untunneledDialConfig)
+				controller.untunneledDialConfig,
+				controller.tlsClientSessionCache)
 
 			if err == nil {
 				lastDownloadTime = time.Now()

+ 1 - 0
psiphon/feedback.go

@@ -231,6 +231,7 @@ func SendFeedback(ctx context.Context, config *Config, diagnostics, uploadPath s
 			feedbackUploadCtx,
 			config,
 			dialConfig,
+			nil,
 			uploadURL.SkipVerify,
 			config.DisableSystemRootCAs,
 			payloadSecure,

+ 14 - 6
psiphon/frontedHTTP.go

@@ -14,6 +14,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
+	utls "github.com/Psiphon-Labs/utls"
 	"github.com/cespare/xxhash"
 )
 
@@ -44,6 +45,7 @@ func newFrontedHTTPClientInstance(
 	skipVerify,
 	disableSystemRootCAs,
 	payloadSecure bool,
+	tlsCache utls.ClientSessionCache,
 ) (*frontedHTTPClientInstance, error) {
 
 	if len(frontingSpecs) == 0 {
@@ -127,7 +129,8 @@ func newFrontedHTTPClientInstance(
 			useDeviceBinder,
 			skipVerify,
 			disableSystemRootCAs,
-			payloadSecure)
+			payloadSecure,
+			tlsCache)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
@@ -140,7 +143,8 @@ func newFrontedHTTPClientInstance(
 			useDeviceBinder,
 			skipVerify,
 			disableSystemRootCAs,
-			payloadSecure)
+			payloadSecure,
+			tlsCache)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
@@ -362,7 +366,8 @@ func makeFrontedHTTPDialParameters(
 	useDeviceBinder,
 	skipVerify,
 	disableSystemRootCAs,
-	payloadSecure bool) (*frontedHTTPDialParameters, error) {
+	payloadSecure bool,
+	tlsCache utls.ClientSessionCache) (*frontedHTTPDialParameters, error) {
 
 	currentTimestamp := time.Now()
 
@@ -382,6 +387,7 @@ func makeFrontedHTTPDialParameters(
 		skipVerify,
 		disableSystemRootCAs,
 		payloadSecure,
+		tlsCache,
 	)
 	if err != nil {
 		return nil, errors.Trace(err)
@@ -397,7 +403,8 @@ func makeFrontedHTTPDialParameters(
 		skipVerify,
 		disableSystemRootCAs,
 		useDeviceBinder,
-		payloadSecure)
+		payloadSecure,
+		tlsCache)
 	if err != nil {
 		return nil, errors.Trace(err)
 	}
@@ -414,7 +421,8 @@ func (dialParams *frontedHTTPDialParameters) prepareDialConfigs(
 	useDeviceBinder,
 	skipVerify,
 	disableSystemRootCAs,
-	payloadSecure bool) error {
+	payloadSecure bool,
+	tlsCache utls.ClientSessionCache) error {
 
 	dialParams.isReplay = isReplay
 
@@ -424,7 +432,7 @@ func (dialParams *frontedHTTPDialParameters) prepareDialConfigs(
 
 		err := dialParams.FrontedMeekDialParameters.prepareDialConfigs(
 			config, p, tunnel, nil, useDeviceBinder, skipVerify,
-			disableSystemRootCAs, payloadSecure)
+			disableSystemRootCAs, payloadSecure, tlsCache)
 		if err != nil {
 			return errors.Trace(err)
 		}

+ 6 - 3
psiphon/frontedHTTP_test.go

@@ -31,6 +31,7 @@ import (
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
+	utls "github.com/Psiphon-Labs/utls"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -123,13 +124,15 @@ func TestFrontedHTTPClientInstance(t *testing.T) {
 
 	// Make fronted HTTP client instance
 
+	tlsCache := utls.NewLRUClientSessionCache(0)
+
 	// TODO: test that replay is disabled when there is a tunnel
 	var tunnel *Tunnel = nil
 	useDeviceBinder := true
 	skipVerify := false
 	payloadSecure := true
 	client, err := newFrontedHTTPClientInstance(
-		config, tunnel, frontingSpecs, nil, useDeviceBinder, skipVerify, config.DisableSystemRootCAs, payloadSecure)
+		config, tunnel, frontingSpecs, nil, useDeviceBinder, skipVerify, config.DisableSystemRootCAs, payloadSecure, tlsCache)
 	if err != nil {
 		t.Fatalf("newFrontedHTTPClientInstance failed: %s", err)
 	}
@@ -140,7 +143,7 @@ func TestFrontedHTTPClientInstance(t *testing.T) {
 	prevClient := client
 
 	client, err = newFrontedHTTPClientInstance(
-		config, tunnel, frontingSpecs, nil, useDeviceBinder, skipVerify, config.DisableSystemRootCAs, payloadSecure)
+		config, tunnel, frontingSpecs, nil, useDeviceBinder, skipVerify, config.DisableSystemRootCAs, payloadSecure, tlsCache)
 	if err != nil {
 		t.Fatalf("newFrontedHTTPClientInstance failed: %s", err)
 	}
@@ -161,7 +164,7 @@ func TestFrontedHTTPClientInstance(t *testing.T) {
 
 	client, err = newFrontedHTTPClientInstance(
 		config, tunnel, frontingSpecs, nil, useDeviceBinder, skipVerify,
-		config.DisableSystemRootCAs, payloadSecure)
+		config.DisableSystemRootCAs, payloadSecure, tlsCache)
 	if err != nil {
 		t.Fatalf("newFrontedHTTPClientInstance failed: %s", err)
 	}

+ 6 - 4
psiphon/frontingDialParameters.go

@@ -93,7 +93,8 @@ func makeFrontedMeekDialParameters(
 	useDeviceBinder,
 	skipVerify,
 	disableSystemRootCAs,
-	payloadSecure bool) (*FrontedMeekDialParameters, error) {
+	payloadSecure bool,
+	tlsCache utls.ClientSessionCache) (*FrontedMeekDialParameters, error) {
 
 	// This function duplicates some code from MakeDialParameters. To simplify
 	// the logic, the Replay<Component> tactic flags for individual dial
@@ -266,7 +267,7 @@ func makeFrontedMeekDialParameters(
 
 	err = frontedMeekDialParams.prepareDialConfigs(
 		config, p, tunnel, dialCustomHeaders, useDeviceBinder, skipVerify,
-		disableSystemRootCAs, payloadSecure)
+		disableSystemRootCAs, payloadSecure, tlsCache)
 	if err != nil {
 		return nil, errors.Trace(err)
 	}
@@ -283,7 +284,8 @@ func (f *FrontedMeekDialParameters) prepareDialConfigs(
 	useDeviceBinder,
 	skipVerify,
 	disableSystemRootCAs,
-	payloadSecure bool) error {
+	payloadSecure bool,
+	tlsCache utls.ClientSessionCache) error {
 
 	if !payloadSecure && (skipVerify || disableSystemRootCAs) {
 		return errors.TraceNew("cannot skip certificate verification if payload insecure")
@@ -410,7 +412,7 @@ func (f *FrontedMeekDialParameters) prepareDialConfigs(
 		// parameters.FrontingSpecs.SelectParameters has couple of issues. For some providers there's
 		// only a couple or even just one possible value, in other cases there are millions of possible values
 		// and cached values won't be used as often as they ought to be.
-		TLSClientSessionCache: common.WrapUtlsClientSessionCache(utls.NewLRUClientSessionCache(0), f.DialAddress),
+		TLSClientSessionCache: common.WrapUtlsClientSessionCache(tlsCache, common.TLS_NULL_SESSION_KEY),
 	}
 
 	if !skipVerify {

+ 19 - 10
psiphon/inproxy.go

@@ -41,6 +41,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/resolver"
+	utls "github.com/Psiphon-Labs/utls"
 	"github.com/cespare/xxhash"
 )
 
@@ -70,6 +71,8 @@ type InproxyBrokerClientManager struct {
 	config  *Config
 	isProxy bool
 
+	tlsCache utls.ClientSessionCache
+
 	mutex                sync.Mutex
 	brokerSelectCount    int
 	networkID            string
@@ -81,11 +84,12 @@ type InproxyBrokerClientManager struct {
 // managed InproxyBrokerClientInstance is initialized when used for a round
 // trip.
 func NewInproxyBrokerClientManager(
-	config *Config, isProxy bool) *InproxyBrokerClientManager {
+	config *Config, isProxy bool, tlsCache utls.ClientSessionCache) *InproxyBrokerClientManager {
 
 	b := &InproxyBrokerClientManager{
-		config:  config,
-		isProxy: isProxy,
+		config:   config,
+		isProxy:  isProxy,
+		tlsCache: tlsCache,
 	}
 
 	// b.brokerClientInstance is initialized on demand, when getBrokerClient
@@ -498,13 +502,13 @@ func NewInproxyBrokerClientInstance(
 	}
 
 	if !isReplay {
-		brokerDialParams, err = MakeInproxyBrokerDialParameters(config, p, networkID, brokerSpec)
+		brokerDialParams, err = MakeInproxyBrokerDialParameters(config, p, networkID, brokerSpec, brokerClientManager.tlsCache)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 	} else {
 		brokerDialParams.brokerSpec = brokerSpec
-		err := brokerDialParams.prepareDialConfigs(config, p, true)
+		err := brokerDialParams.prepareDialConfigs(config, p, true, brokerClientManager.tlsCache)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
@@ -1161,7 +1165,8 @@ func MakeInproxyBrokerDialParameters(
 	config *Config,
 	p parameters.ParametersAccessor,
 	networkID string,
-	brokerSpec *parameters.InproxyBrokerSpec) (*InproxyBrokerDialParameters, error) {
+	brokerSpec *parameters.InproxyBrokerSpec,
+	tlsCache utls.ClientSessionCache) (*InproxyBrokerDialParameters, error) {
 
 	if config.UseUpstreamProxy() {
 		return nil, errors.TraceNew("upstream proxy unsupported")
@@ -1196,7 +1201,9 @@ func MakeInproxyBrokerDialParameters(
 		true,
 		skipVerify,
 		config.DisableSystemRootCAs,
-		payloadSecure)
+		payloadSecure,
+		tlsCache,
+	)
 	if err != nil {
 		return nil, errors.Trace(err)
 	}
@@ -1206,7 +1213,8 @@ func MakeInproxyBrokerDialParameters(
 	err = brokerDialParams.prepareDialConfigs(
 		config,
 		p,
-		false)
+		false,
+		tlsCache)
 	if err != nil {
 		return nil, errors.Trace(err)
 	}
@@ -1218,7 +1226,8 @@ func MakeInproxyBrokerDialParameters(
 func (brokerDialParams *InproxyBrokerDialParameters) prepareDialConfigs(
 	config *Config,
 	p parameters.ParametersAccessor,
-	isReplay bool) error {
+	isReplay bool,
+	tlsCache utls.ClientSessionCache) error {
 
 	brokerDialParams.isReplay = isReplay
 
@@ -1237,7 +1246,7 @@ func (brokerDialParams *InproxyBrokerDialParameters) prepareDialConfigs(
 
 		err := brokerDialParams.FrontedHTTPDialParameters.prepareDialConfigs(
 			config, p, nil, nil, true, skipVerify,
-			config.DisableSystemRootCAs, payloadSecure)
+			config.DisableSystemRootCAs, payloadSecure, tlsCache)
 		if err != nil {
 			return errors.Trace(err)
 		}

+ 9 - 6
psiphon/inproxy_test.go

@@ -31,6 +31,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/resolver"
+	utls "github.com/Psiphon-Labs/utls"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -110,7 +111,9 @@ func runInproxyBrokerDialParametersTest(t *testing.T) error {
 	}
 	defer CloseDataStore()
 
-	manager := NewInproxyBrokerClientManager(config, isProxy)
+	tlsCache := utls.NewLRUClientSessionCache(0)
+
+	manager := NewInproxyBrokerClientManager(config, isProxy, tlsCache)
 
 	// Test: no broker specs
 
@@ -136,7 +139,7 @@ func runInproxyBrokerDialParametersTest(t *testing.T) error {
 	}
 	config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
 
-	manager = NewInproxyBrokerClientManager(config, isProxy)
+	manager = NewInproxyBrokerClientManager(config, isProxy, tlsCache)
 
 	brokerClient, brokerDialParams, err := manager.GetBrokerClient(networkID)
 	if err != nil {
@@ -170,7 +173,7 @@ func runInproxyBrokerDialParametersTest(t *testing.T) error {
 
 	brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripperSucceeded(roundTripper)
 
-	manager = NewInproxyBrokerClientManager(config, isProxy)
+	manager = NewInproxyBrokerClientManager(config, isProxy, tlsCache)
 
 	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
 	if err != nil {
@@ -247,7 +250,7 @@ func runInproxyBrokerDialParametersTest(t *testing.T) error {
 
 	brokerClient.GetBrokerDialCoordinator().BrokerClientRoundTripperFailed(roundTripper)
 
-	manager = NewInproxyBrokerClientManager(config, isProxy)
+	manager = NewInproxyBrokerClientManager(config, isProxy, tlsCache)
 
 	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
 	if err != nil {
@@ -269,7 +272,7 @@ func runInproxyBrokerDialParametersTest(t *testing.T) error {
 	config.InproxyClientPersonalCompartmentID = personalCompartmentID.String()
 	config.InproxyProxyPersonalCompartmentID = personalCompartmentID.String()
 
-	manager = NewInproxyBrokerClientManager(config, isProxy)
+	manager = NewInproxyBrokerClientManager(config, isProxy, tlsCache)
 
 	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
 	if err != nil {
@@ -298,7 +301,7 @@ func runInproxyBrokerDialParametersTest(t *testing.T) error {
 	}
 	config.SetResolver(resolver.NewResolver(&resolver.NetworkConfig{}, networkID))
 
-	manager = NewInproxyBrokerClientManager(config, isProxy)
+	manager = NewInproxyBrokerClientManager(config, isProxy, tlsCache)
 
 	brokerClient, brokerDialParams, err = manager.GetBrokerClient(networkID)
 	if err != nil {

+ 14 - 5
psiphon/net.go

@@ -429,11 +429,12 @@ func makeFrontedHTTPClient(
 	useDeviceBinder,
 	skipVerify,
 	disableSystemRootCAs,
-	payloadSecure bool) (*http.Client, func() common.APIParameters, error) {
+	payloadSecure bool,
+	tlsCache utls.ClientSessionCache) (*http.Client, func() common.APIParameters, error) {
 
 	frontedHTTPClient, err := newFrontedHTTPClientInstance(
 		config, tunnel, frontingSpecs, selectedFrontingProviderID,
-		useDeviceBinder, skipVerify, disableSystemRootCAs, payloadSecure)
+		useDeviceBinder, skipVerify, disableSystemRootCAs, payloadSecure, tlsCache)
 	if err != nil {
 		return nil, nil, errors.Trace(err)
 	}
@@ -487,6 +488,7 @@ func MakeUntunneledHTTPClient(
 	ctx context.Context,
 	config *Config,
 	untunneledDialConfig *DialConfig,
+	tlsCache utls.ClientSessionCache,
 	skipVerify bool,
 	disableSystemRootCAs bool,
 	payloadSecure bool,
@@ -511,7 +513,9 @@ func MakeUntunneledHTTPClient(
 			frontingUseDeviceBinder,
 			false,
 			disableSystemRootCAs,
-			payloadSecure)
+			payloadSecure,
+			tlsCache,
+		)
 		if err != nil {
 			return nil, nil, errors.Trace(err)
 		}
@@ -528,7 +532,7 @@ func MakeUntunneledHTTPClient(
 		SkipVerify:                    skipVerify,
 		DisableSystemRootCAs:          disableSystemRootCAs,
 		TrustedCACertificatesFilename: untunneledDialConfig.TrustedCACertificatesFilename,
-		ClientSessionCache:            utls.NewLRUClientSessionCache(0),
+		ClientSessionCache:            tlsCache,
 	}
 
 	tlsDialer := NewCustomTLSDialer(tlsConfig)
@@ -557,6 +561,7 @@ func MakeTunneledHTTPClient(
 	ctx context.Context,
 	config *Config,
 	tunnel *Tunnel,
+	tlsCache utls.ClientSessionCache,
 	skipVerify,
 	disableSystemRootCAs,
 	payloadSecure bool,
@@ -578,7 +583,8 @@ func MakeTunneledHTTPClient(
 			false,
 			false,
 			disableSystemRootCAs,
-			payloadSecure)
+			payloadSecure,
+			tlsCache)
 		if err != nil {
 			return nil, nil, errors.Trace(err)
 		}
@@ -627,6 +633,7 @@ func MakeDownloadHTTPClient(
 	config *Config,
 	tunnel *Tunnel,
 	untunneledDialConfig *DialConfig,
+	tlsCache utls.ClientSessionCache,
 	skipVerify,
 	disableSystemRootCAs,
 	payloadSecure bool,
@@ -646,6 +653,7 @@ func MakeDownloadHTTPClient(
 			ctx,
 			config,
 			tunnel,
+			tlsCache,
 			skipVerify || disableSystemRootCAs,
 			disableSystemRootCAs,
 			payloadSecure,
@@ -667,6 +675,7 @@ func MakeDownloadHTTPClient(
 			ctx,
 			config,
 			dialConfig,
+			tlsCache,
 			skipVerify,
 			disableSystemRootCAs,
 			payloadSecure,

+ 13 - 3
psiphon/remoteServerList.go

@@ -33,10 +33,11 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/osl"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
+	utls "github.com/Psiphon-Labs/utls"
 )
 
 type RemoteServerListFetcher func(
-	ctx context.Context, config *Config, attempt int, tunnel *Tunnel, untunneledDialConfig *DialConfig) error
+	ctx context.Context, config *Config, attempt int, tunnel *Tunnel, untunneledDialConfig *DialConfig, tlsCache utls.ClientSessionCache) error
 
 // FetchCommonRemoteServerList downloads the common remote server list from
 // config.RemoteServerListURLs. It validates its digital signature using the
@@ -50,7 +51,8 @@ func FetchCommonRemoteServerList(
 	config *Config,
 	attempt int,
 	tunnel *Tunnel,
-	untunneledDialConfig *DialConfig) error {
+	untunneledDialConfig *DialConfig,
+	tlsCache utls.ClientSessionCache) error {
 
 	NoticeInfo("fetching common remote server list")
 
@@ -68,6 +70,7 @@ func FetchCommonRemoteServerList(
 		config,
 		tunnel,
 		untunneledDialConfig,
+		tlsCache,
 		downloadTimeout,
 		downloadURL.URL,
 		canonicalURL,
@@ -145,7 +148,8 @@ func FetchObfuscatedServerLists(
 	config *Config,
 	attempt int,
 	tunnel *Tunnel,
-	untunneledDialConfig *DialConfig) error {
+	untunneledDialConfig *DialConfig,
+	tlsCache utls.ClientSessionCache) error {
 
 	NoticeInfo("fetching obfuscated remote server lists")
 
@@ -192,6 +196,7 @@ func FetchObfuscatedServerLists(
 		config,
 		tunnel,
 		untunneledDialConfig,
+		tlsCache,
 		downloadTimeout,
 		downloadURL,
 		canonicalURL,
@@ -272,6 +277,7 @@ func FetchObfuscatedServerLists(
 			config,
 			tunnel,
 			untunneledDialConfig,
+			tlsCache,
 			downloadTimeout,
 			rootURL,
 			canonicalRootURL,
@@ -325,6 +331,7 @@ func downloadOSLFileSpec(
 	config *Config,
 	tunnel *Tunnel,
 	untunneledDialConfig *DialConfig,
+	tlsCache utls.ClientSessionCache,
 	downloadTimeout time.Duration,
 	rootURL *parameters.TransferURL,
 	canonicalRootURL string,
@@ -349,6 +356,7 @@ func downloadOSLFileSpec(
 		config,
 		tunnel,
 		untunneledDialConfig,
+		tlsCache,
 		downloadTimeout,
 		downloadURL,
 		canonicalURL,
@@ -433,6 +441,7 @@ func downloadRemoteServerListFile(
 	config *Config,
 	tunnel *Tunnel,
 	untunneledDialConfig *DialConfig,
+	tlsCache utls.ClientSessionCache,
 	downloadTimeout time.Duration,
 	sourceURL string,
 	canonicalURL string,
@@ -472,6 +481,7 @@ func downloadRemoteServerListFile(
 		config,
 		tunnel,
 		untunneledDialConfig,
+		tlsCache,
 		skipVerify,
 		disableSystemRootCAs,
 		payloadSecure,

+ 4 - 1
psiphon/tactics_test.go

@@ -30,6 +30,7 @@ import (
 	"time"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
+	utls "github.com/Psiphon-Labs/utls"
 )
 
 func TestStandAloneGetTactics(t *testing.T) {
@@ -108,7 +109,9 @@ func TestStandAloneGetTactics(t *testing.T) {
 		UpstreamProxyURL: config.UpstreamProxyURL,
 	}
 
-	err = FetchCommonRemoteServerList(ctx, config, 0, nil, untunneledDialConfig)
+	tlsCache := utls.NewLRUClientSessionCache(0)
+
+	err = FetchCommonRemoteServerList(ctx, config, 0, nil, untunneledDialConfig, tlsCache)
 	if err != nil {
 		t.Fatalf("error fetching remote server list: %s", err)
 	}

+ 4 - 1
psiphon/upgradeDownload.go

@@ -28,6 +28,7 @@ import (
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
+	utls "github.com/Psiphon-Labs/utls"
 )
 
 // DownloadUpgrade performs a resumable download of client upgrade files.
@@ -61,7 +62,8 @@ func DownloadUpgrade(
 	attempt int,
 	handshakeVersion string,
 	tunnel *Tunnel,
-	untunneledDialConfig *DialConfig) error {
+	untunneledDialConfig *DialConfig,
+	tlsCache utls.ClientSessionCache) error {
 
 	// Note: this downloader doesn't use ETags since many client binaries, with
 	// different embedded values, exist for a single version.
@@ -94,6 +96,7 @@ func DownloadUpgrade(
 		config,
 		tunnel,
 		untunneledDialConfig,
+		tlsCache,
 		downloadURL.SkipVerify,
 		config.DisableSystemRootCAs,
 		payloadSecure,