Răsfoiți Sursa

Add obfuscated PSK to TLS-OSSH

* Control client use of PSK in TLS-OSSH with a tactic probability
* Accept session tickets encrypted with MeekObfuscatedKey
Amir Khan 1 an în urmă
părinte
comite
e349ac2963

+ 2 - 0
psiphon/common/parameters/parameters.go

@@ -362,6 +362,7 @@ const (
 	OSSHPrefixSplitMaxDelay                            = "OSSHPrefixSplitMaxDelay"
 	OSSHPrefixEnableFragmentor                         = "OSSHPrefixEnableFragmentor"
 	ServerOSSHPrefixSpecs                              = "ServerOSSHPrefixSpecs"
+	TLSTunnelObfuscatedPSKProbability                  = "TLSTunnelObfuscatedPSKProbability"
 	TLSTunnelTrafficShapingProbability                 = "TLSTunnelTrafficShapingProbability"
 	TLSTunnelMinTLSPadding                             = "TLSTunnelMinTLSPadding"
 	TLSTunnelMaxTLSPadding                             = "TLSTunnelMaxTLSPadding"
@@ -846,6 +847,7 @@ var defaultParameters = map[string]struct {
 
 	// TLSTunnelMinTLSPadding/TLSTunnelMaxTLSPadding are subject to TLS server limitations.
 
+	TLSTunnelObfuscatedPSKProbability:  {value: 0.5, minimum: 0.0},
 	TLSTunnelTrafficShapingProbability: {value: 1.0, minimum: 0.0},
 	TLSTunnelMinTLSPadding:             {value: 0, minimum: 0},
 	TLSTunnelMaxTLSPadding:             {value: 0, minimum: 0},

+ 10 - 0
psiphon/config.go

@@ -987,6 +987,7 @@ type Config struct {
 	OSSHPrefixEnableFragmentor          *bool
 
 	// TLSTunnelTrafficShapingProbability and associated fields are for testing.
+	TLSTunnelObfuscatedPSKProbability  *float64
 	TLSTunnelTrafficShapingProbability *float64
 	TLSTunnelMinTLSPadding             *int
 	TLSTunnelMaxTLSPadding             *int
@@ -2357,6 +2358,10 @@ func (config *Config) makeConfigParameters() map[string]interface{} {
 		applyParameters[parameters.OSSHPrefixEnableFragmentor] = *config.OSSHPrefixEnableFragmentor
 	}
 
+	if config.TLSTunnelObfuscatedPSKProbability != nil {
+		applyParameters[parameters.TLSTunnelObfuscatedPSKProbability] = *config.TLSTunnelObfuscatedPSKProbability
+	}
+
 	if config.TLSTunnelTrafficShapingProbability != nil {
 		applyParameters[parameters.TLSTunnelTrafficShapingProbability] = *config.TLSTunnelTrafficShapingProbability
 	}
@@ -3169,6 +3174,11 @@ func (config *Config) setDialParametersHash() {
 		binary.Write(hash, binary.LittleEndian, *config.OSSHPrefixEnableFragmentor)
 	}
 
+	if config.TLSTunnelObfuscatedPSKProbability != nil {
+		hash.Write([]byte("TLSTunnelObfuscatedPSKProbability"))
+		binary.Write(hash, binary.LittleEndian, *config.TLSTunnelObfuscatedPSKProbability)
+	}
+
 	if config.TLSTunnelTrafficShapingProbability != nil {
 		hash.Write([]byte("TLSTunnelTrafficShapingProbability"))
 		binary.Write(hash, binary.LittleEndian, *config.TLSTunnelTrafficShapingProbability)

+ 4 - 2
psiphon/dialParameters.go

@@ -1598,6 +1598,9 @@ func (dialParams *DialParameters) GetMeekConfig() *MeekConfig {
 
 func (dialParams *DialParameters) GetTLSOSSHConfig(config *Config) *TLSTunnelConfig {
 
+	p := config.GetParameters().Get()
+	useObfuscatedPSK := p.WeightedCoinFlip(parameters.TLSTunnelObfuscatedPSKProbability)
+
 	// TLSTunnelConfig isn't pre-created in MakeDialParameters to avoid holding a long
 	// term reference to TLSTunnelConfig.Parameters.
 
@@ -1615,8 +1618,7 @@ func (dialParams *DialParameters) GetTLSOSSHConfig(config *Config) *TLSTunnelCon
 			FragmentClientHello:      dialParams.TLSFragmentClientHello,
 			ClientSessionCache:       dialParams.tlsClientSessionCache,
 		},
-		// Obfuscated session tickets are not used because TLS-OSSH uses TLS 1.3.
-		UseObfuscatedSessionTickets: false,
+		UseObfuscatedSessionTickets: useObfuscatedPSK,
 		// Meek obfuscated key used to allow clients with legacy unfronted
 		// meek-https server entries, that have the passthrough capability, to
 		// connect with TLS-OSSH to the servers corresponding to those server

+ 33 - 2
psiphon/server/tlsTunnel.go

@@ -20,6 +20,9 @@
 package server
 
 import (
+	"crypto/rand"
+	"encoding/hex"
+	std_errors "errors"
 	"net"
 
 	tls "github.com/Psiphon-Labs/psiphon-tls"
@@ -81,7 +84,7 @@ func NewTLSTunnelServer(
 		obfuscatorSeedHistory:  obfuscator.NewSeedHistory(nil),
 	}
 
-	tlsConfig, err := tlsServer.makeTLSTunnelConfig()
+	tlsConfig, err := tlsServer.makeTLSTunnelConfig(support.Config.MeekObfuscatedKey)
 	if err != nil {
 		return nil, errors.Trace(err)
 	}
@@ -91,7 +94,7 @@ func NewTLSTunnelServer(
 }
 
 // makeTLSTunnelConfig creates a TLS config for a TLSTunnelServer listener.
-func (server *TLSTunnelServer) makeTLSTunnelConfig() (*tls.Config, error) {
+func (server *TLSTunnelServer) makeTLSTunnelConfig(sessionTicketKey string) (*tls.Config, error) {
 
 	// Limitation: certificate value changes on restart.
 
@@ -124,6 +127,34 @@ func (server *TLSTunnelServer) makeTLSTunnelConfig() (*tls.Config, error) {
 		MinVersion:   minVersion,
 	}
 
+	if sessionTicketKey != "" {
+		// See obfuscated session ticket overview
+		// in NewObfuscatedClientSessionState.
+
+		config.UseObfuscatedSessionTickets = true
+
+		var obfuscatedSessionTicketKey [32]byte
+		key, err := hex.DecodeString(server.support.Config.MeekObfuscatedKey)
+		if err == nil && len(key) != 32 {
+			err = std_errors.New("invalid obfuscated session key length")
+		}
+		if err != nil {
+			return nil, errors.Trace(err)
+		}
+		copy(obfuscatedSessionTicketKey[:], key)
+
+		var standardSessionTicketKey [32]byte
+		_, err = rand.Read(standardSessionTicketKey[:])
+		if err != nil {
+			return nil, errors.Trace(err)
+		}
+
+		config.SessionTicketKey = obfuscatedSessionTicketKey
+		config.SetSessionTicketKeys([][32]byte{
+			standardSessionTicketKey,
+			obfuscatedSessionTicketKey})
+	}
+
 	// When configured, initialize passthrough mode, an anti-probing defense.
 	// Clients must prove knowledge of the obfuscated key via a message sent in
 	// the TLS ClientHello random field.