Răsfoiți Sursa

Updated psiphon-tls

Amir Khan 2 ani în urmă
părinte
comite
47ee0a71a7

+ 2 - 2
go.mod

@@ -10,8 +10,8 @@ require (
 	github.com/Psiphon-Inc/rotate-safe-writer v0.0.0-20210303140923-464a7a37606e
 	github.com/Psiphon-Inc/rotate-safe-writer v0.0.0-20210303140923-464a7a37606e
 	github.com/Psiphon-Labs/bolt v0.0.0-20200624191537-23cedaef7ad7
 	github.com/Psiphon-Labs/bolt v0.0.0-20200624191537-23cedaef7ad7
 	github.com/Psiphon-Labs/goptlib v0.0.0-20200406165125-c0e32a7a3464
 	github.com/Psiphon-Labs/goptlib v0.0.0-20200406165125-c0e32a7a3464
-	github.com/Psiphon-Labs/psiphon-tls v0.0.0-20240206031303-574af011ca51
-	github.com/Psiphon-Labs/quic-go v0.0.0-20240206031737-eae23f995bd7
+	github.com/Psiphon-Labs/psiphon-tls v0.0.0-20240301004115-0bd3fb6285a1
+	github.com/Psiphon-Labs/quic-go v0.0.0-20240301182333-dc6bf1a9bcb8
 	github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f
 	github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f
 	github.com/bifurcation/mint v0.0.0-20180306135233-198357931e61
 	github.com/bifurcation/mint v0.0.0-20180306135233-198357931e61
 	github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9
 	github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9

+ 4 - 4
go.sum

@@ -13,12 +13,12 @@ github.com/Psiphon-Labs/bolt v0.0.0-20200624191537-23cedaef7ad7 h1:Hx/NCZTnvoKZu
 github.com/Psiphon-Labs/bolt v0.0.0-20200624191537-23cedaef7ad7/go.mod h1:alTtZBo3j4AWFvUrAH6F5ZaHcTj4G5Y01nHz8dkU6vU=
 github.com/Psiphon-Labs/bolt v0.0.0-20200624191537-23cedaef7ad7/go.mod h1:alTtZBo3j4AWFvUrAH6F5ZaHcTj4G5Y01nHz8dkU6vU=
 github.com/Psiphon-Labs/goptlib v0.0.0-20200406165125-c0e32a7a3464 h1:VmnMMMheFXwLV0noxYhbJbLmkV4iaVW3xNnj6xcCNHo=
 github.com/Psiphon-Labs/goptlib v0.0.0-20200406165125-c0e32a7a3464 h1:VmnMMMheFXwLV0noxYhbJbLmkV4iaVW3xNnj6xcCNHo=
 github.com/Psiphon-Labs/goptlib v0.0.0-20200406165125-c0e32a7a3464/go.mod h1:Pe5BqN2DdIdChorAXl6bDaQd/wghpCleJfid2NoSli0=
 github.com/Psiphon-Labs/goptlib v0.0.0-20200406165125-c0e32a7a3464/go.mod h1:Pe5BqN2DdIdChorAXl6bDaQd/wghpCleJfid2NoSli0=
-github.com/Psiphon-Labs/psiphon-tls v0.0.0-20240206031303-574af011ca51 h1:SiQ9M1g2fUWHVf0AgyssaiDFuzjX9s0vPbnUtCk+GJQ=
-github.com/Psiphon-Labs/psiphon-tls v0.0.0-20240206031303-574af011ca51/go.mod h1:MzvOK7DlXAkfZ7wrgwQmBoBsbo22c9qaz2JYlEXwoTk=
+github.com/Psiphon-Labs/psiphon-tls v0.0.0-20240301004115-0bd3fb6285a1 h1:4u8RKSYC2QfE6NPll+75MRzhTPFnMVNLGLqN4oNBRKg=
+github.com/Psiphon-Labs/psiphon-tls v0.0.0-20240301004115-0bd3fb6285a1/go.mod h1:MzvOK7DlXAkfZ7wrgwQmBoBsbo22c9qaz2JYlEXwoTk=
 github.com/Psiphon-Labs/qtls-go1-20 v0.0.0-20231117202359-5544003bda6f h1:x33cklt4AZ9K8a9EpmFLjIxjZwPXeWWb124OYstlTmA=
 github.com/Psiphon-Labs/qtls-go1-20 v0.0.0-20231117202359-5544003bda6f h1:x33cklt4AZ9K8a9EpmFLjIxjZwPXeWWb124OYstlTmA=
 github.com/Psiphon-Labs/qtls-go1-20 v0.0.0-20231117202359-5544003bda6f/go.mod h1:f6akxitY5DYvGtbI+LkDSvw0bctE75P63bX6nb0V+eg=
 github.com/Psiphon-Labs/qtls-go1-20 v0.0.0-20231117202359-5544003bda6f/go.mod h1:f6akxitY5DYvGtbI+LkDSvw0bctE75P63bX6nb0V+eg=
-github.com/Psiphon-Labs/quic-go v0.0.0-20240206031737-eae23f995bd7 h1:PvrEqpGt2dVuC8AJkD4tmSjRRO61jNnKCgg5wsXrysA=
-github.com/Psiphon-Labs/quic-go v0.0.0-20240206031737-eae23f995bd7/go.mod h1:x+q9fpp7vneF9oQjBHkQS7W3jsLJqL3/X18psW4YdkY=
+github.com/Psiphon-Labs/quic-go v0.0.0-20240301182333-dc6bf1a9bcb8 h1:c0Fk7rT46yUV6Vvi7l2pdEGxHW1p9MKCnADyFab8GJY=
+github.com/Psiphon-Labs/quic-go v0.0.0-20240301182333-dc6bf1a9bcb8/go.mod h1:LxrlIAcjMVG/ou+WPE/vuCaV7jvCLYc2AWxe+66Yqgs=
 github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
 github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
 github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f h1:SaJ6yqg936TshyeFZqQE+N+9hYkIeL9AMr7S4voCl10=
 github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f h1:SaJ6yqg936TshyeFZqQE+N+9hYkIeL9AMr7S4voCl10=

+ 25 - 26
psiphon/server/meek.go

@@ -115,8 +115,7 @@ type MeekServer struct {
 	skipExtendedTurnAroundThreshold int
 	skipExtendedTurnAroundThreshold int
 	maxSessionStaleness             time.Duration
 	maxSessionStaleness             time.Duration
 	httpClientIOTimeout             time.Duration
 	httpClientIOTimeout             time.Duration
-	tlsConfig                       *tls.Config
-	tlsExtraConfig                  *tls.ExtraConfig
+	tlsConfig                       *tls.ExtendedTLSConfig
 	obfuscatorSeedHistory           *obfuscator.SeedHistory
 	obfuscatorSeedHistory           *obfuscator.SeedHistory
 	clientHandler                   func(clientConn net.Conn, data *additionalTransportData)
 	clientHandler                   func(clientConn net.Conn, data *additionalTransportData)
 	openConns                       *common.Conns
 	openConns                       *common.Conns
@@ -233,13 +232,12 @@ func NewMeekServer(
 	}
 	}
 
 
 	if useTLS {
 	if useTLS {
-		tlsConfig, extraConfig, err := meekServer.makeMeekTLSConfig(
+		tlsConfig, err := meekServer.makeMeekTLSConfig(
 			isFronted, useObfuscatedSessionTickets)
 			isFronted, useObfuscatedSessionTickets)
 		if err != nil {
 		if err != nil {
 			return nil, errors.Trace(err)
 			return nil, errors.Trace(err)
 		}
 		}
 		meekServer.tlsConfig = tlsConfig
 		meekServer.tlsConfig = tlsConfig
-		meekServer.tlsExtraConfig = extraConfig
 	}
 	}
 
 
 	if useHTTPNormalizer && protocol.TunnelProtocolUsesMeekHTTPNormalizer(listenerTunnelProtocol) {
 	if useHTTPNormalizer && protocol.TunnelProtocolUsesMeekHTTPNormalizer(listenerTunnelProtocol) {
@@ -315,7 +313,7 @@ func (server *MeekServer) Run() error {
 	var err error
 	var err error
 	if server.tlsConfig != nil {
 	if server.tlsConfig != nil {
 		httpsServer := HTTPSServer{Server: httpServer}
 		httpsServer := HTTPSServer{Server: httpServer}
-		err = httpsServer.ServeTLS(server.listener, server.tlsConfig, server.tlsExtraConfig)
+		err = httpsServer.ServeTLS(server.listener, server.tlsConfig)
 	} else {
 	} else {
 		err = httpServer.Serve(server.listener)
 		err = httpServer.Serve(server.listener)
 	}
 	}
@@ -1221,17 +1219,17 @@ func (server *MeekServer) getMeekCookiePayload(
 // of the connection is non-circumvention; it's optimized for performance
 // of the connection is non-circumvention; it's optimized for performance
 // assuming the peer is an uncensored CDN.
 // assuming the peer is an uncensored CDN.
 func (server *MeekServer) makeMeekTLSConfig(
 func (server *MeekServer) makeMeekTLSConfig(
-	isFronted bool, useObfuscatedSessionTickets bool) (*tls.Config, *tls.ExtraConfig, error) {
+	isFronted bool, useObfuscatedSessionTickets bool) (*tls.ExtendedTLSConfig, error) {
 
 
 	certificate, privateKey, err := common.GenerateWebServerCertificate(values.GetHostName())
 	certificate, privateKey, err := common.GenerateWebServerCertificate(values.GetHostName())
 	if err != nil {
 	if err != nil {
-		return nil, nil, errors.Trace(err)
+		return nil, errors.Trace(err)
 	}
 	}
 
 
 	tlsCertificate, err := tls.X509KeyPair(
 	tlsCertificate, err := tls.X509KeyPair(
 		[]byte(certificate), []byte(privateKey))
 		[]byte(certificate), []byte(privateKey))
 	if err != nil {
 	if err != nil {
-		return nil, nil, errors.Trace(err)
+		return nil, errors.Trace(err)
 	}
 	}
 
 
 	// Vary the minimum version to frustrate scanning/fingerprinting of unfronted servers.
 	// Vary the minimum version to frustrate scanning/fingerprinting of unfronted servers.
@@ -1239,14 +1237,15 @@ func (server *MeekServer) makeMeekTLSConfig(
 	minVersionCandidates := []uint16{tls.VersionTLS10, tls.VersionTLS11, tls.VersionTLS12}
 	minVersionCandidates := []uint16{tls.VersionTLS10, tls.VersionTLS11, tls.VersionTLS12}
 	minVersion := minVersionCandidates[prng.Intn(len(minVersionCandidates))]
 	minVersion := minVersionCandidates[prng.Intn(len(minVersionCandidates))]
 
 
-	config := &tls.Config{
-		Certificates: []tls.Certificate{tlsCertificate},
-		NextProtos:   []string{"http/1.1"},
-		MinVersion:   minVersion,
+	config := &tls.ExtendedTLSConfig{
+		TLSConfig: &tls.Config{
+			Certificates: []tls.Certificate{tlsCertificate},
+			NextProtos:   []string{"http/1.1"},
+			MinVersion:   minVersion,
+		},
+		ExtraConfig: &tls.ExtraConfig{},
 	}
 	}
 
 
-	extraConfig := &tls.ExtraConfig{}
-
 	if isFronted {
 	if isFronted {
 		// This is a reordering of the supported CipherSuites in golang 1.6[*]. Non-ephemeral key
 		// This is a reordering of the supported CipherSuites in golang 1.6[*]. Non-ephemeral key
 		// CipherSuites greatly reduce server load, and we try to select these since the meek
 		// CipherSuites greatly reduce server load, and we try to select these since the meek
@@ -1259,7 +1258,7 @@ func (server *MeekServer) makeMeekTLSConfig(
 		// unfronted cases we prefer a more natural TLS handshake.
 		// unfronted cases we prefer a more natural TLS handshake.
 		//
 		//
 		// [*] the list has since been updated, removing CipherSuites using RC4 and 3DES.
 		// [*] the list has since been updated, removing CipherSuites using RC4 and 3DES.
-		config.CipherSuites = []uint16{
+		config.TLSConfig.CipherSuites = []uint16{
 			tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
 			tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
 			tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
 			tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
 			tls.TLS_RSA_WITH_AES_128_CBC_SHA,
 			tls.TLS_RSA_WITH_AES_128_CBC_SHA,
@@ -1273,7 +1272,7 @@ func (server *MeekServer) makeMeekTLSConfig(
 			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
 			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
 			tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
 			tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
 		}
 		}
-		config.PreferServerCipherSuites = true
+		config.TLSConfig.PreferServerCipherSuites = true
 	}
 	}
 
 
 	if useObfuscatedSessionTickets {
 	if useObfuscatedSessionTickets {
@@ -1281,7 +1280,7 @@ func (server *MeekServer) makeMeekTLSConfig(
 		// See obfuscated session ticket overview
 		// See obfuscated session ticket overview
 		// in NewObfuscatedClientSessionState.
 		// in NewObfuscatedClientSessionState.
 
 
-		extraConfig.UseObfuscatedSessionTickets = true
+		config.ExtraConfig.UseObfuscatedSessionTickets = true
 
 
 		var obfuscatedSessionTicketKey [32]byte
 		var obfuscatedSessionTicketKey [32]byte
 		key, err := hex.DecodeString(server.support.Config.MeekObfuscatedKey)
 		key, err := hex.DecodeString(server.support.Config.MeekObfuscatedKey)
@@ -1289,21 +1288,21 @@ func (server *MeekServer) makeMeekTLSConfig(
 			err = std_errors.New("invalid obfuscated session key length")
 			err = std_errors.New("invalid obfuscated session key length")
 		}
 		}
 		if err != nil {
 		if err != nil {
-			return nil, nil, errors.Trace(err)
+			return nil, errors.Trace(err)
 		}
 		}
 		copy(obfuscatedSessionTicketKey[:], key)
 		copy(obfuscatedSessionTicketKey[:], key)
 
 
 		var standardSessionTicketKey [32]byte
 		var standardSessionTicketKey [32]byte
 		_, err = rand.Read(standardSessionTicketKey[:])
 		_, err = rand.Read(standardSessionTicketKey[:])
 		if err != nil {
 		if err != nil {
-			return nil, nil, errors.Trace(err)
+			return nil, errors.Trace(err)
 		}
 		}
 
 
 		// Note: SessionTicketKey needs to be set, or else, it appears,
 		// Note: SessionTicketKey needs to be set, or else, it appears,
 		// tris.Config.serverInit() will clobber the value set by
 		// tris.Config.serverInit() will clobber the value set by
 		// SetSessionTicketKeys.
 		// SetSessionTicketKeys.
-		config.SessionTicketKey = obfuscatedSessionTicketKey
-		config.SetSessionTicketKeys([][32]byte{
+		config.TLSConfig.SessionTicketKey = obfuscatedSessionTicketKey
+		config.TLSConfig.SetSessionTicketKeys([][32]byte{
 			standardSessionTicketKey,
 			standardSessionTicketKey,
 			obfuscatedSessionTicketKey})
 			obfuscatedSessionTicketKey})
 	}
 	}
@@ -1321,9 +1320,9 @@ func (server *MeekServer) makeMeekTLSConfig(
 
 
 	if server.passthroughAddress != "" {
 	if server.passthroughAddress != "" {
 
 
-		extraConfig.PassthroughAddress = server.passthroughAddress
+		config.ExtraConfig.PassthroughAddress = server.passthroughAddress
 
 
-		extraConfig.PassthroughVerifyMessage = func(
+		config.ExtraConfig.PassthroughVerifyMessage = func(
 			message []byte) bool {
 			message []byte) bool {
 
 
 			return obfuscator.VerifyTLSPassthroughMessage(
 			return obfuscator.VerifyTLSPassthroughMessage(
@@ -1332,7 +1331,7 @@ func (server *MeekServer) makeMeekTLSConfig(
 				message)
 				message)
 		}
 		}
 
 
-		extraConfig.PassthroughLogInvalidMessage = func(
+		config.ExtraConfig.PassthroughLogInvalidMessage = func(
 			clientIP string) {
 			clientIP string) {
 
 
 			logIrregularTunnel(
 			logIrregularTunnel(
@@ -1344,7 +1343,7 @@ func (server *MeekServer) makeMeekTLSConfig(
 				nil)
 				nil)
 		}
 		}
 
 
-		extraConfig.PassthroughHistoryAddNew = func(
+		config.ExtraConfig.PassthroughHistoryAddNew = func(
 			clientIP string,
 			clientIP string,
 			clientRandom []byte) bool {
 			clientRandom []byte) bool {
 
 
@@ -1379,7 +1378,7 @@ func (server *MeekServer) makeMeekTLSConfig(
 		}
 		}
 	}
 	}
 
 
-	return config, extraConfig, nil
+	return config, nil
 }
 }
 
 
 // makeMeekHTTPNormalizerListener returns the meek server listener wrapped in
 // makeMeekHTTPNormalizerListener returns the meek server listener wrapped in

+ 2 - 2
psiphon/server/net.go

@@ -73,7 +73,7 @@ type HTTPSServer struct {
 //
 //
 // Note that the http.Server.TLSConfig field is ignored and the tls.Config
 // Note that the http.Server.TLSConfig field is ignored and the tls.Config
 // parameter is used intead.
 // parameter is used intead.
-func (server *HTTPSServer) ServeTLS(listener net.Listener, config *tls.Config, extraConfig *tls.ExtraConfig) error {
-	tlsListener := tls.NewListener(listener, config, extraConfig)
+func (server *HTTPSServer) ServeTLS(listener net.Listener, config *tls.ExtendedTLSConfig) error {
+	tlsListener := tls.NewListener(listener, config)
 	return server.Serve(tlsListener)
 	return server.Serve(tlsListener)
 }
 }

+ 18 - 19
psiphon/server/tlsTunnel.go

@@ -39,8 +39,7 @@ type TLSTunnelServer struct {
 	listenerTunnelProtocol string
 	listenerTunnelProtocol string
 	listenerPort           int
 	listenerPort           int
 	passthroughAddress     string
 	passthroughAddress     string
-	tlsConfig              *tls.Config
-	extraConfig            *tls.ExtraConfig
+	tlsConfig              *tls.ExtendedTLSConfig
 	obfuscatorSeedHistory  *obfuscator.SeedHistory
 	obfuscatorSeedHistory  *obfuscator.SeedHistory
 }
 }
 
 
@@ -59,7 +58,7 @@ func ListenTLSTunnel(
 		return nil, errors.Trace(err)
 		return nil, errors.Trace(err)
 	}
 	}
 
 
-	listener = tls.NewListener(server.listener, server.tlsConfig, server.extraConfig)
+	listener = tls.NewListener(server.listener, server.tlsConfig)
 
 
 	return NewTLSTunnelListener(listener, server), nil
 	return NewTLSTunnelListener(listener, server), nil
 }
 }
@@ -82,30 +81,29 @@ func NewTLSTunnelServer(
 		obfuscatorSeedHistory:  obfuscator.NewSeedHistory(nil),
 		obfuscatorSeedHistory:  obfuscator.NewSeedHistory(nil),
 	}
 	}
 
 
-	tlsConfig, extraConfig, err := tlsServer.makeTLSTunnelConfig()
+	tlsConfig, err := tlsServer.makeTLSTunnelConfig()
 	if err != nil {
 	if err != nil {
 		return nil, errors.Trace(err)
 		return nil, errors.Trace(err)
 	}
 	}
 	tlsServer.tlsConfig = tlsConfig
 	tlsServer.tlsConfig = tlsConfig
-	tlsServer.extraConfig = extraConfig
 
 
 	return tlsServer, nil
 	return tlsServer, nil
 }
 }
 
 
 // makeTLSTunnelConfig creates a TLS config for a TLSTunnelServer listener.
 // makeTLSTunnelConfig creates a TLS config for a TLSTunnelServer listener.
-func (server *TLSTunnelServer) makeTLSTunnelConfig() (*tls.Config, *tls.ExtraConfig, error) {
+func (server *TLSTunnelServer) makeTLSTunnelConfig() (*tls.ExtendedTLSConfig, error) {
 
 
 	// Limitation: certificate value changes on restart.
 	// Limitation: certificate value changes on restart.
 
 
 	certificate, privateKey, err := common.GenerateWebServerCertificate(values.GetHostName())
 	certificate, privateKey, err := common.GenerateWebServerCertificate(values.GetHostName())
 	if err != nil {
 	if err != nil {
-		return nil, nil, errors.Trace(err)
+		return nil, errors.Trace(err)
 	}
 	}
 
 
 	tlsCertificate, err := tls.X509KeyPair(
 	tlsCertificate, err := tls.X509KeyPair(
 		[]byte(certificate), []byte(privateKey))
 		[]byte(certificate), []byte(privateKey))
 	if err != nil {
 	if err != nil {
-		return nil, nil, errors.Trace(err)
+		return nil, errors.Trace(err)
 	}
 	}
 
 
 	var minVersion uint16
 	var minVersion uint16
@@ -120,14 +118,15 @@ func (server *TLSTunnelServer) makeTLSTunnelConfig() (*tls.Config, *tls.ExtraCon
 		minVersion = minVersionCandidates[prng.Intn(len(minVersionCandidates))]
 		minVersion = minVersionCandidates[prng.Intn(len(minVersionCandidates))]
 	}
 	}
 
 
-	config := &tls.Config{
-		Certificates: []tls.Certificate{tlsCertificate},
-		NextProtos:   []string{"http/1.1"},
-		MinVersion:   minVersion,
+	config := &tls.ExtendedTLSConfig{
+		TLSConfig: &tls.Config{
+			Certificates: []tls.Certificate{tlsCertificate},
+			NextProtos:   []string{"http/1.1"},
+			MinVersion:   minVersion,
+		},
+		ExtraConfig: &tls.ExtraConfig{},
 	}
 	}
 
 
-	extraConfig := &tls.ExtraConfig{}
-
 	// When configured, initialize passthrough mode, an anti-probing defense.
 	// When configured, initialize passthrough mode, an anti-probing defense.
 	// Clients must prove knowledge of the obfuscated key via a message sent in
 	// Clients must prove knowledge of the obfuscated key via a message sent in
 	// the TLS ClientHello random field.
 	// the TLS ClientHello random field.
@@ -141,9 +140,9 @@ func (server *TLSTunnelServer) makeTLSTunnelConfig() (*tls.Config, *tls.ExtraCon
 
 
 	if server.passthroughAddress != "" {
 	if server.passthroughAddress != "" {
 
 
-		extraConfig.PassthroughAddress = server.passthroughAddress
+		config.ExtraConfig.PassthroughAddress = server.passthroughAddress
 
 
-		extraConfig.PassthroughVerifyMessage = func(
+		config.ExtraConfig.PassthroughVerifyMessage = func(
 			message []byte) bool {
 			message []byte) bool {
 
 
 			return obfuscator.VerifyTLSPassthroughMessage(
 			return obfuscator.VerifyTLSPassthroughMessage(
@@ -154,7 +153,7 @@ func (server *TLSTunnelServer) makeTLSTunnelConfig() (*tls.Config, *tls.ExtraCon
 				message)
 				message)
 		}
 		}
 
 
-		extraConfig.PassthroughLogInvalidMessage = func(
+		config.ExtraConfig.PassthroughLogInvalidMessage = func(
 			clientIP string) {
 			clientIP string) {
 
 
 			logIrregularTunnel(
 			logIrregularTunnel(
@@ -166,7 +165,7 @@ func (server *TLSTunnelServer) makeTLSTunnelConfig() (*tls.Config, *tls.ExtraCon
 				nil)
 				nil)
 		}
 		}
 
 
-		extraConfig.PassthroughHistoryAddNew = func(
+		config.ExtraConfig.PassthroughHistoryAddNew = func(
 			clientIP string,
 			clientIP string,
 			clientRandom []byte) bool {
 			clientRandom []byte) bool {
 
 
@@ -198,7 +197,7 @@ func (server *TLSTunnelServer) makeTLSTunnelConfig() (*tls.Config, *tls.ExtraCon
 		}
 		}
 	}
 	}
 
 
-	return config, extraConfig, nil
+	return config, nil
 }
 }
 
 
 // TLSTunnelListener implements the net.Listener interface. Accept returns a
 // TLSTunnelListener implements the net.Listener interface. Accept returns a

+ 1 - 1
psiphon/server/webServer.go

@@ -122,7 +122,7 @@ func RunWebServer(
 		defer waitGroup.Done()
 		defer waitGroup.Done()
 
 
 		// Note: will be interrupted by listener.Close()
 		// Note: will be interrupted by listener.Close()
-		err := server.ServeTLS(listener, tlsConfig)
+		err := server.ServeTLS(listener, &tls.ExtendedTLSConfig{TLSConfig: tlsConfig})
 
 
 		// Can't check for the exact error that Close() will cause in Accept(),
 		// Can't check for the exact error that Close() will cause in Accept(),
 		// (see: https://code.google.com/p/go/issues/detail?id=4373). So using an
 		// (see: https://code.google.com/p/go/issues/detail?id=4373). So using an

+ 13 - 11
psiphon/sessionTicket_test.go

@@ -34,6 +34,7 @@ import (
 	"time"
 	"time"
 
 
 	tls "github.com/Psiphon-Labs/psiphon-tls"
 	tls "github.com/Psiphon-Labs/psiphon-tls"
+
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	utls "github.com/refraction-networking/utls"
 	utls "github.com/refraction-networking/utls"
@@ -76,21 +77,22 @@ func runObfuscatedSessionTicket(t *testing.T, tlsProfile string) {
 		t.Fatalf("generateCertificate failed: %s", err)
 		t.Fatalf("generateCertificate failed: %s", err)
 	}
 	}
 
 
-	serverConfig := &tls.Config{
-		Certificates: []tls.Certificate{*certificate},
-		NextProtos:   []string{"http/1.1"},
-		MinVersion:   utls.VersionTLS12,
-	}
-
-	extraConfig := &tls.ExtraConfig{
-		UseObfuscatedSessionTickets: true,
+	serverConfig := &tls.ExtendedTLSConfig{
+		TLSConfig: &tls.Config{
+			Certificates: []tls.Certificate{*certificate},
+			NextProtos:   []string{"http/1.1"},
+			MinVersion:   utls.VersionTLS12,
+		},
+		ExtraConfig: &tls.ExtraConfig{
+			UseObfuscatedSessionTickets: true,
+		},
 	}
 	}
 
 
 	// Note: SessionTicketKey needs to be set, or else, it appears,
 	// Note: SessionTicketKey needs to be set, or else, it appears,
 	// tris.Config.serverInit() will clobber the value set by
 	// tris.Config.serverInit() will clobber the value set by
 	// SetSessionTicketKeys.
 	// SetSessionTicketKeys.
-	serverConfig.SessionTicketKey = obfuscatedSessionTicketSharedSecret
-	serverConfig.SetSessionTicketKeys([][32]byte{
+	serverConfig.TLSConfig.SessionTicketKey = obfuscatedSessionTicketSharedSecret
+	serverConfig.TLSConfig.SetSessionTicketKeys([][32]byte{
 		standardSessionTicketKey, obfuscatedSessionTicketSharedSecret})
 		standardSessionTicketKey, obfuscatedSessionTicketSharedSecret})
 
 
 	testMessage := "test"
 	testMessage := "test"
@@ -108,7 +110,7 @@ func runObfuscatedSessionTicket(t *testing.T, tlsProfile string) {
 
 
 	go func() {
 	go func() {
 
 
-		listener, err := tls.Listen("tcp", ":0", serverConfig, extraConfig)
+		listener, err := tls.Listen("tcp", ":0", serverConfig)
 		if err != nil {
 		if err != nil {
 			report(err)
 			report(err)
 			return
 			return

+ 6 - 5
psiphon/tlsDialer_test.go

@@ -418,10 +418,11 @@ func initTestCertificatesAndWebServer(
 
 
 	listener = tls.NewListener(
 	listener = tls.NewListener(
 		listener,
 		listener,
-		&tls.Config{
-			Certificates: []tls.Certificate{serverKeyPair},
-		},
-		nil)
+		&tls.ExtendedTLSConfig{
+			TLSConfig: &tls.Config{
+				Certificates: []tls.Certificate{serverKeyPair},
+			},
+		})
 
 
 	var wg sync.WaitGroup
 	var wg sync.WaitGroup
 	wg.Add(1)
 	wg.Add(1)
@@ -515,7 +516,7 @@ func testTLSDialerCompatibility(t *testing.T, address string, fragmentClientHell
 			t.Fatalf("net.Listen failed: %v", err)
 			t.Fatalf("net.Listen failed: %v", err)
 		}
 		}
 
 
-		tlsListener := tls.NewListener(tcpListener, config, nil)
+		tlsListener := tls.NewListener(tcpListener, &tls.ExtendedTLSConfig{TLSConfig: config})
 		defer tlsListener.Close()
 		defer tlsListener.Close()
 
 
 		address = tlsListener.Addr().String()
 		address = tlsListener.Addr().String()

+ 7 - 0
vendor/github.com/Psiphon-Labs/psiphon-tls/common.go

@@ -807,6 +807,13 @@ type ExtraConfig struct {
 	PassthroughLogInvalidMessage func(clientIP string)
 	PassthroughLogInvalidMessage func(clientIP string)
 }
 }
 
 
+// [Psiphon]
+// ExtendedTLSConfig wraps crypto/tls.Config and Psiphon-specific configurations.
+type ExtendedTLSConfig struct {
+	TLSConfig   *Config
+	ExtraConfig *ExtraConfig
+}
+
 const (
 const (
 	// ticketKeyLifetime is how long a ticket key remains valid and can be used to
 	// ticketKeyLifetime is how long a ticket key remains valid and can be used to
 	// resume a client connection.
 	// resume a client connection.

+ 8 - 0
vendor/github.com/Psiphon-Labs/psiphon-tls/handshake_messages.go

@@ -541,6 +541,14 @@ func (m *clientHelloMsg) marshalRandomized() []byte {
 					}
 					}
 				},
 				},
 
 
+				func() {
+					if m.extendedMasterSecret {
+						// RFC 7627
+						b.AddUint16(extensionExtendedMasterSecret)
+						b.AddUint16(0) // empty extension_data
+					}
+				},
+
 				func() {
 				func() {
 					if len(m.alpnProtocols) > 0 {
 					if len(m.alpnProtocols) > 0 {
 						// RFC 7301, Section 3.1
 						// RFC 7301, Section 3.1

+ 6 - 2
vendor/github.com/Psiphon-Labs/psiphon-tls/quic.go

@@ -142,7 +142,11 @@ type quicState struct {
 //
 //
 // The config's MinVersion must be at least TLS 1.3.
 // The config's MinVersion must be at least TLS 1.3.
 func QUICClient(config *QUICConfig) *QUICConn {
 func QUICClient(config *QUICConfig) *QUICConn {
-	return newQUICConn(Client(nil, config.TLSConfig, config.ExtraConfig))
+	tlsConfig := &ExtendedTLSConfig{
+		TLSConfig:   config.TLSConfig,
+		ExtraConfig: config.ExtraConfig,
+	}
+	return newQUICConn(Client(nil, tlsConfig))
 }
 }
 
 
 // QUICServer returns a new TLS server side connection using QUICTransport as the
 // QUICServer returns a new TLS server side connection using QUICTransport as the
@@ -150,7 +154,7 @@ func QUICClient(config *QUICConfig) *QUICConn {
 //
 //
 // The config's MinVersion must be at least TLS 1.3.
 // The config's MinVersion must be at least TLS 1.3.
 func QUICServer(config *QUICConfig) *QUICConn {
 func QUICServer(config *QUICConfig) *QUICConn {
-	return newQUICConn(Server(nil, config.TLSConfig, config.ExtraConfig))
+	return newQUICConn(Server(nil, &ExtendedTLSConfig{TLSConfig: config.TLSConfig, ExtraConfig: config.ExtraConfig}))
 }
 }
 
 
 func newQUICConn(conn *Conn) *QUICConn {
 func newQUICConn(conn *Conn) *QUICConn {

+ 15 - 17
vendor/github.com/Psiphon-Labs/psiphon-tls/tls.go

@@ -31,19 +31,19 @@ import (
 // using conn as the underlying transport.
 // using conn as the underlying transport.
 // The configuration config must be non-nil and must include
 // The configuration config must be non-nil and must include
 // at least one certificate or else set GetCertificate.
 // at least one certificate or else set GetCertificate.
-func Server(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn {
+func Server(conn net.Conn, config *ExtendedTLSConfig) *Conn {
 
 
 	// [Psiphon]
 	// [Psiphon]
 	// Initialize traffic recording to facilitate playback in the case of
 	// Initialize traffic recording to facilitate playback in the case of
 	// passthrough.
 	// passthrough.
-	if extraConfig != nil && extraConfig.PassthroughAddress != "" {
+	if config.ExtraConfig != nil && config.ExtraConfig.PassthroughAddress != "" {
 		conn = newRecorderConn(conn)
 		conn = newRecorderConn(conn)
 	}
 	}
 
 
 	c := &Conn{
 	c := &Conn{
 		conn:        conn,
 		conn:        conn,
-		config:      fromConfig(config),
-		extraConfig: extraConfig,
+		config:      fromConfig(config.TLSConfig),
+		extraConfig: config.ExtraConfig,
 	}
 	}
 	c.handshakeFn = c.serverHandshake
 	c.handshakeFn = c.serverHandshake
 	return c
 	return c
@@ -53,11 +53,11 @@ func Server(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn {
 // using conn as the underlying transport.
 // using conn as the underlying transport.
 // The config cannot be nil: users must set either ServerName or
 // The config cannot be nil: users must set either ServerName or
 // InsecureSkipVerify in the config.
 // InsecureSkipVerify in the config.
-func Client(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn {
+func Client(conn net.Conn, config *ExtendedTLSConfig) *Conn {
 	c := &Conn{
 	c := &Conn{
 		conn:        conn,
 		conn:        conn,
-		config:      fromConfig(config),
-		extraConfig: extraConfig,
+		config:      fromConfig(config.TLSConfig),
+		extraConfig: config.ExtraConfig,
 		isClient:    true,
 		isClient:    true,
 	}
 	}
 	c.handshakeFn = c.clientHandshake
 	c.handshakeFn = c.clientHandshake
@@ -67,8 +67,7 @@ func Client(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn {
 // A listener implements a network listener (net.Listener) for TLS connections.
 // A listener implements a network listener (net.Listener) for TLS connections.
 type listener struct {
 type listener struct {
 	net.Listener
 	net.Listener
-	config      *Config
-	extraConfig *ExtraConfig
+	config *ExtendedTLSConfig
 }
 }
 
 
 // Accept waits for and returns the next incoming TLS connection.
 // Accept waits for and returns the next incoming TLS connection.
@@ -78,18 +77,17 @@ func (l *listener) Accept() (net.Conn, error) {
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	return Server(c, l.config, l.extraConfig), nil
+	return Server(c, l.config), nil
 }
 }
 
 
 // NewListener creates a Listener which accepts connections from an inner
 // NewListener creates a Listener which accepts connections from an inner
 // Listener and wraps each connection with Server.
 // Listener and wraps each connection with Server.
 // The configuration config must be non-nil and must include
 // The configuration config must be non-nil and must include
 // at least one certificate or else set GetCertificate.
 // at least one certificate or else set GetCertificate.
-func NewListener(inner net.Listener, config *Config, extraConfig *ExtraConfig) net.Listener {
+func NewListener(inner net.Listener, config *ExtendedTLSConfig) net.Listener {
 	l := new(listener)
 	l := new(listener)
 	l.Listener = inner
 	l.Listener = inner
 	l.config = config
 	l.config = config
-	l.extraConfig = extraConfig
 	return l
 	return l
 }
 }
 
 
@@ -97,16 +95,16 @@ func NewListener(inner net.Listener, config *Config, extraConfig *ExtraConfig) n
 // given network address using net.Listen.
 // given network address using net.Listen.
 // The configuration config must be non-nil and must include
 // The configuration config must be non-nil and must include
 // at least one certificate or else set GetCertificate.
 // at least one certificate or else set GetCertificate.
-func Listen(network, laddr string, config *Config, extraConfig *ExtraConfig) (net.Listener, error) {
-	if config == nil || len(config.Certificates) == 0 &&
-		config.GetCertificate == nil && config.GetConfigForClient == nil {
+func Listen(network, laddr string, config *ExtendedTLSConfig) (net.Listener, error) {
+	if config == nil || len(config.TLSConfig.Certificates) == 0 &&
+		config.TLSConfig.GetCertificate == nil && config.TLSConfig.GetConfigForClient == nil {
 		return nil, errors.New("tls: neither Certificates, GetCertificate, nor GetConfigForClient set in Config")
 		return nil, errors.New("tls: neither Certificates, GetCertificate, nor GetConfigForClient set in Config")
 	}
 	}
 	l, err := net.Listen(network, laddr)
 	l, err := net.Listen(network, laddr)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	return NewListener(l, config, extraConfig), nil
+	return NewListener(l, config), nil
 }
 }
 
 
 type timeoutError struct{}
 type timeoutError struct{}
@@ -165,7 +163,7 @@ func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, conf
 		config = c
 		config = c
 	}
 	}
 
 
-	conn := Client(rawConn, config, nil)
+	conn := Client(rawConn, &ExtendedTLSConfig{TLSConfig: config})
 	if err := conn.HandshakeContext(ctx); err != nil {
 	if err := conn.HandshakeContext(ctx); err != nil {
 		rawConn.Close()
 		rawConn.Close()
 		return nil, err
 		return nil, err

+ 6 - 31
vendor/github.com/Psiphon-Labs/quic-go/framer.go

@@ -23,8 +23,6 @@ type framer interface {
 	Handle0RTTRejection() error
 	Handle0RTTRejection() error
 }
 }
 
 
-const maxPathResponses = 256
-
 type framerI struct {
 type framerI struct {
 	mutex sync.Mutex
 	mutex sync.Mutex
 
 
@@ -35,7 +33,6 @@ type framerI struct {
 
 
 	controlFrameMutex sync.Mutex
 	controlFrameMutex sync.Mutex
 	controlFrames     []wire.Frame
 	controlFrames     []wire.Frame
-	pathResponses     []*wire.PathResponseFrame
 }
 }
 
 
 var _ framer = &framerI{}
 var _ framer = &framerI{}
@@ -55,43 +52,20 @@ func (f *framerI) HasData() bool {
 		return true
 		return true
 	}
 	}
 	f.controlFrameMutex.Lock()
 	f.controlFrameMutex.Lock()
-	defer f.controlFrameMutex.Unlock()
-	return len(f.controlFrames) > 0 || len(f.pathResponses) > 0
+	hasData = len(f.controlFrames) > 0
+	f.controlFrameMutex.Unlock()
+	return hasData
 }
 }
 
 
 func (f *framerI) QueueControlFrame(frame wire.Frame) {
 func (f *framerI) QueueControlFrame(frame wire.Frame) {
 	f.controlFrameMutex.Lock()
 	f.controlFrameMutex.Lock()
-	defer f.controlFrameMutex.Unlock()
-
-	if pr, ok := frame.(*wire.PathResponseFrame); ok {
-		// Only queue up to maxPathResponses PATH_RESPONSE frames.
-		// This limit should be high enough to never be hit in practice,
-		// unless the peer is doing something malicious.
-		if len(f.pathResponses) >= maxPathResponses {
-			return
-		}
-		f.pathResponses = append(f.pathResponses, pr)
-		return
-	}
 	f.controlFrames = append(f.controlFrames, frame)
 	f.controlFrames = append(f.controlFrames, frame)
+	f.controlFrameMutex.Unlock()
 }
 }
 
 
 func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount) {
 func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount) {
-	f.controlFrameMutex.Lock()
-	defer f.controlFrameMutex.Unlock()
-
 	var length protocol.ByteCount
 	var length protocol.ByteCount
-	// add a PATH_RESPONSE first, but only pack a single PATH_RESPONSE per packet
-	if len(f.pathResponses) > 0 {
-		frame := f.pathResponses[0]
-		frameLen := frame.Length(v)
-		if frameLen <= maxLen {
-			frames = append(frames, ackhandler.Frame{Frame: frame})
-			length += frameLen
-			f.pathResponses = f.pathResponses[1:]
-		}
-	}
-
+	f.controlFrameMutex.Lock()
 	for len(f.controlFrames) > 0 {
 	for len(f.controlFrames) > 0 {
 		frame := f.controlFrames[len(f.controlFrames)-1]
 		frame := f.controlFrames[len(f.controlFrames)-1]
 		frameLen := frame.Length(v)
 		frameLen := frame.Length(v)
@@ -102,6 +76,7 @@ func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol
 		length += frameLen
 		length += frameLen
 		f.controlFrames = f.controlFrames[:len(f.controlFrames)-1]
 		f.controlFrames = f.controlFrames[:len(f.controlFrames)-1]
 	}
 	}
+	f.controlFrameMutex.Unlock()
 	return frames, length
 	return frames, length
 }
 }
 
 

+ 1 - 0
vendor/github.com/Psiphon-Labs/quic-go/internal/handshake/crypto_setup.go

@@ -106,6 +106,7 @@ func NewCryptoSetupClient(
 
 
 	tlsConf = tlsConf.Clone()
 	tlsConf = tlsConf.Clone()
 	tlsConf.MinVersion = tls.VersionTLS13
 	tlsConf.MinVersion = tls.VersionTLS13
+
 	quicConf := &qtls.QUICConfig{
 	quicConf := &qtls.QUICConfig{
 		TLSConfig: tlsConf,
 		TLSConfig: tlsConf,
 
 

+ 4 - 2
vendor/github.com/Psiphon-Labs/quic-go/internal/qtls/go120.go

@@ -54,8 +54,10 @@ func SetupConfigForServer(conf *QUICConfig, enable0RTT bool, getDataForSessionTi
 }
 }
 
 
 func SetupConfigForClient(conf *QUICConfig, getDataForSessionState func() []byte, setDataFromSessionState func([]byte) bool) {
 func SetupConfigForClient(conf *QUICConfig, getDataForSessionState func() []byte, setDataFromSessionState func([]byte) bool) {
-	conf.ExtraConfig.GetAppDataForSessionState = getDataForSessionState
-	conf.ExtraConfig.SetAppDataFromSessionState = setDataFromSessionState
+	conf.ExtraConfig = &qtls.ExtraConfig{
+		GetAppDataForSessionState:  getDataForSessionState,
+		SetAppDataFromSessionState: setDataFromSessionState,
+	}
 }
 }
 
 
 func QUICServer(config *QUICConfig) *QUICConn {
 func QUICServer(config *QUICConfig) *QUICConn {

+ 1 - 0
vendor/github.com/Psiphon-Labs/quic-go/internal/qtls/go121.go

@@ -14,6 +14,7 @@ type (
 	QUICConn                 = tls.QUICConn
 	QUICConn                 = tls.QUICConn
 	QUICConfig               = tls.QUICConfig
 	QUICConfig               = tls.QUICConfig
 	ExtraConfig              = tls.ExtraConfig
 	ExtraConfig              = tls.ExtraConfig
+	ExtendedTLSConfig        = tls.ExtendedTLSConfig
 	QUICEvent                = tls.QUICEvent
 	QUICEvent                = tls.QUICEvent
 	QUICEventKind            = tls.QUICEventKind
 	QUICEventKind            = tls.QUICEventKind
 	QUICEncryptionLevel      = tls.QUICEncryptionLevel
 	QUICEncryptionLevel      = tls.QUICEncryptionLevel

+ 1 - 7
vendor/github.com/Psiphon-Labs/quic-go/packet_packer.go

@@ -640,13 +640,7 @@ func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, onlyAc
 		pl.length += lengthAdded
 		pl.length += lengthAdded
 		// add handlers for the control frames that were added
 		// add handlers for the control frames that were added
 		for i := startLen; i < len(pl.frames); i++ {
 		for i := startLen; i < len(pl.frames); i++ {
-			switch pl.frames[i].Frame.(type) {
-			case *wire.PathChallengeFrame, *wire.PathResponseFrame:
-				// Path probing is currently not supported, therefore we don't need to set the OnAcked callback yet.
-				// PATH_CHALLENGE and PATH_RESPONSE are never retransmitted.
-			default:
-				pl.frames[i].Handler = p.retransmissionQueue.AppDataAckHandler()
-			}
+			pl.frames[i].Handler = p.retransmissionQueue.AppDataAckHandler()
 		}
 		}
 
 
 		pl.streamFrames, lengthAdded = p.framer.AppendStreamFrames(pl.streamFrames, maxFrameSize-pl.length, v)
 		pl.streamFrames, lengthAdded = p.framer.AppendStreamFrames(pl.streamFrames, maxFrameSize-pl.length, v)

+ 2 - 2
vendor/modules.txt

@@ -20,13 +20,13 @@ github.com/Psiphon-Labs/bolt
 # github.com/Psiphon-Labs/goptlib v0.0.0-20200406165125-c0e32a7a3464
 # github.com/Psiphon-Labs/goptlib v0.0.0-20200406165125-c0e32a7a3464
 ## explicit
 ## explicit
 github.com/Psiphon-Labs/goptlib
 github.com/Psiphon-Labs/goptlib
-# github.com/Psiphon-Labs/psiphon-tls v0.0.0-20240206031303-574af011ca51
+# github.com/Psiphon-Labs/psiphon-tls v0.0.0-20240301004115-0bd3fb6285a1
 ## explicit; go 1.20
 ## explicit; go 1.20
 github.com/Psiphon-Labs/psiphon-tls
 github.com/Psiphon-Labs/psiphon-tls
 # github.com/Psiphon-Labs/qtls-go1-20 v0.0.0-20231117202359-5544003bda6f
 # github.com/Psiphon-Labs/qtls-go1-20 v0.0.0-20231117202359-5544003bda6f
 ## explicit; go 1.20
 ## explicit; go 1.20
 github.com/Psiphon-Labs/qtls-go1-20
 github.com/Psiphon-Labs/qtls-go1-20
-# github.com/Psiphon-Labs/quic-go v0.0.0-20240206031737-eae23f995bd7
+# github.com/Psiphon-Labs/quic-go v0.0.0-20240301182333-dc6bf1a9bcb8
 ## explicit; go 1.20
 ## explicit; go 1.20
 github.com/Psiphon-Labs/quic-go
 github.com/Psiphon-Labs/quic-go
 github.com/Psiphon-Labs/quic-go/http3
 github.com/Psiphon-Labs/quic-go/http3