Browse Source

Added protocol limit to TLSFragmentClientHelllo

Amir Khan 2 years ago
parent
commit
5d46095951
4 changed files with 37 additions and 19 deletions
  1. 3 1
      psiphon/common/parameters/parameters.go
  2. 14 2
      psiphon/config.go
  3. 17 13
      psiphon/dialParameters.go
  4. 3 3
      psiphon/meekConn.go

+ 3 - 1
psiphon/common/parameters/parameters.go

@@ -349,6 +349,7 @@ const (
 	TLSTunnelMinTLSPadding                           = "TLSTunnelMinTLSPadding"
 	TLSTunnelMaxTLSPadding                           = "TLSTunnelMaxTLSPadding"
 	TLSFragmentClientHelloProbability                = "TLSFragmentClientHelloProbability"
+	TLSFragmentClientHelloLimitProtocols             = "TLSFragmentClientHelloLimitProtocols"
 
 	// Retired parameters
 
@@ -745,7 +746,8 @@ var defaultParameters = map[string]struct {
 	TLSTunnelMinTLSPadding:             {value: 0, minimum: 0},
 	TLSTunnelMaxTLSPadding:             {value: 0, minimum: 0},
 
-	TLSFragmentClientHelloProbability: {value: 0.0, minimum: 0.0},
+	TLSFragmentClientHelloProbability:    {value: 0.0, minimum: 0.0},
+	TLSFragmentClientHelloLimitProtocols: {value: protocol.TunnelProtocols{}},
 }
 
 // IsServerSideOnly indicates if the parameter specified by name is used

+ 14 - 2
psiphon/config.go

@@ -872,8 +872,9 @@ type Config struct {
 	TLSTunnelMinTLSPadding             *int
 	TLSTunnelMaxTLSPadding             *int
 
-	// TLSFragmentClientHelloProbability is for testing purposes only.
-	TLSFragmentClientHelloProbability *float64
+	// TLSFragmentClientHello fields are for testing purposes only.
+	TLSFragmentClientHelloProbability    *float64
+	TLSFragmentClientHelloLimitProtocols []string
 
 	// AdditionalParameters is used for testing.
 	AdditionalParameters string
@@ -2064,6 +2065,10 @@ func (config *Config) makeConfigParameters() map[string]interface{} {
 		applyParameters[parameters.TLSFragmentClientHelloProbability] = *config.TLSFragmentClientHelloProbability
 	}
 
+	if len(config.TLSFragmentClientHelloLimitProtocols) > 0 {
+		applyParameters[parameters.TLSFragmentClientHelloLimitProtocols] = protocol.TunnelProtocols(config.TLSFragmentClientHelloLimitProtocols)
+	}
+
 	// When adding new config dial parameters that may override tactics, also
 	// update setDialParametersHash.
 
@@ -2600,6 +2605,13 @@ func (config *Config) setDialParametersHash() {
 		binary.Write(hash, binary.LittleEndian, *config.TLSFragmentClientHelloProbability)
 	}
 
+	if len(config.TLSFragmentClientHelloLimitProtocols) > 0 {
+		hash.Write([]byte("TLSFragmentClientHelloLimitProtocols"))
+		for _, protocol := range config.TLSFragmentClientHelloLimitProtocols {
+			hash.Write([]byte(protocol))
+		}
+	}
+
 	config.dialParametersHash = hash.Sum(nil)
 }
 

+ 17 - 13
psiphon/dialParameters.go

@@ -1021,21 +1021,25 @@ func MakeDialParameters(
 	// of SNI is determined above.
 	if (!isReplay || !replayTLSFragmentClientHello) && usingTLS {
 
-		// Note: The TLS stack automatically drops the SNI extension when
-		// the host is an IP address.
+		limitProtocols := p.TunnelProtocols(parameters.TLSFragmentClientHelloLimitProtocols)
+		if len(limitProtocols) == 0 || common.Contains(limitProtocols, dialParams.TunnelProtocol) {
 
-		usingSNI := false
-		if dialParams.TLSOSSHSNIServerName != "" {
-			usingSNI = net.ParseIP(dialParams.TLSOSSHSNIServerName) == nil
+			// Note: The TLS stack automatically drops the SNI extension when
+			// the host is an IP address.
 
-		} else if dialParams.MeekSNIServerName != "" {
-			usingSNI = net.ParseIP(dialParams.MeekSNIServerName) == nil
-		}
+			usingSNI := false
+			if dialParams.TLSOSSHSNIServerName != "" {
+				usingSNI = net.ParseIP(dialParams.TLSOSSHSNIServerName) == nil
+
+			} else if dialParams.MeekSNIServerName != "" {
+				usingSNI = net.ParseIP(dialParams.MeekSNIServerName) == nil
+			}
 
-		// TLS ClientHello fragmentor expects SNI to be present.
-		if usingSNI {
-			dialParams.TLSFragmentClientHello = p.WeightedCoinFlip(
-				parameters.TLSFragmentClientHelloProbability)
+			// TLS ClientHello fragmentor expects SNI to be present.
+			if usingSNI {
+				dialParams.TLSFragmentClientHello = p.WeightedCoinFlip(
+					parameters.TLSFragmentClientHelloProbability)
+			}
 		}
 	}
 
@@ -1152,6 +1156,7 @@ func MakeDialParameters(
 			QUICDisablePathMTUDiscovery:   dialParams.QUICDisablePathMTUDiscovery,
 			UseHTTPS:                      usingTLS,
 			TLSProfile:                    dialParams.TLSProfile,
+			TLSFragmentClientHello:        dialParams.TLSFragmentClientHello,
 			LegacyPassthrough:             serverEntry.ProtocolUsesLegacyPassthrough(dialParams.TunnelProtocol),
 			NoDefaultTLSSessionID:         dialParams.NoDefaultTLSSessionID,
 			RandomizedTLSProfileSeed:      dialParams.RandomizedTLSProfileSeed,
@@ -1169,7 +1174,6 @@ func MakeDialParameters(
 			MeekObfuscatorPaddingSeed:     dialParams.MeekObfuscatorPaddingSeed,
 			NetworkLatencyMultiplier:      dialParams.NetworkLatencyMultiplier,
 			HTTPTransformerParameters:     dialParams.HTTPTransformerParameters,
-			TLSFragmentClientHello:        dialParams.TLSFragmentClientHello,
 		}
 
 		// Use an asynchronous callback to record the resolved IP address when

+ 3 - 3
psiphon/meekConn.go

@@ -131,6 +131,9 @@ type MeekConfig struct {
 	// underlying TLS connections created by this meek connection.
 	TLSProfile string
 
+	// TLSFragmentClientHello specifies whether to fragment the TLS Client Hello.
+	TLSFragmentClientHello bool
+
 	// LegacyPassthrough indicates that the server expects a legacy passthrough
 	// message.
 	LegacyPassthrough bool
@@ -207,9 +210,6 @@ type MeekConfig struct {
 	// HTTPTransformerParameters specifies an HTTP transformer to apply to the
 	// meek connection if it uses HTTP.
 	HTTPTransformerParameters *transforms.HTTPTransformerParameters
-
-	// TLSFragmentClientHello specifies whether to fragment the TLS Client Hello.
-	TLSFragmentClientHello bool
 }
 
 // MeekConn is a network connection that tunnels net.Conn flows over HTTP and supports