Просмотр исходного кода

Support specific client/proxy BrokerSpec tactics and common STUN tactics

Rod Hynes 1 год назад
Родитель
Сommit
7ed74d4eb3
5 измененных файлов с 137 добавлено и 34 удалено
  1. 27 5
      psiphon/common/parameters/parameters.go
  2. 20 0
      psiphon/config.go
  3. 11 3
      psiphon/controller.go
  4. 18 9
      psiphon/inproxy.go
  5. 61 17
      psiphon/server/server_test.go

+ 27 - 5
psiphon/common/parameters/parameters.go

@@ -374,6 +374,8 @@ const (
 	InproxyTunnelProtocolSelectionProbability          = "InproxyTunnelProtocolSelectionProbability"
 	InproxyAllBrokerPublicKeys                         = "InproxyAllBrokerPublicKeys"
 	InproxyBrokerSpecs                                 = "InproxyBrokerSpecs"
+	InproxyProxyBrokerSpecs                            = "InproxyProxyBrokerSpecs"
+	InproxyClientBrokerSpecs                           = "InproxyClientBrokerSpecs"
 	InproxyReplayBrokerDialParametersTTL               = "InproxyReplayBrokerDialParametersTTL"
 	InproxyReplayBrokerUpdateFrequency                 = "InproxyReplayBrokerUpdateFrequency"
 	InproxyReplayBrokerDialParametersProbability       = "InproxyReplayBrokerDialParametersProbability"
@@ -402,6 +404,8 @@ const (
 	InproxyDTLSRandomizationProbability                = "InproxyDTLSRandomizationProbability"
 	InproxyDataChannelTrafficShapingProbability        = "InproxyDataChannelTrafficShapingProbability"
 	InproxyDataChannelTrafficShapingParameters         = "InproxyDataChannelTrafficShapingParameters"
+	InproxySTUNServerAddresses                         = "InproxySTUNServerAddresses"
+	InproxySTUNServerAddressesRFC5780                  = "InproxySTUNServerAddressesRFC5780"
 	InproxyProxySTUNServerAddresses                    = "InproxyProxySTUNServerAddresses"
 	InproxyProxySTUNServerAddressesRFC5780             = "InproxyProxySTUNServerAddressesRFC5780"
 	InproxyClientSTUNServerAddresses                   = "InproxyClientSTUNServerAddresses"
@@ -848,6 +852,8 @@ var defaultParameters = map[string]struct {
 	InproxyTunnelProtocolSelectionProbability:          {value: 0.5, minimum: 0.0},
 	InproxyAllBrokerPublicKeys:                         {value: []string{}, flags: serverSideOnly},
 	InproxyBrokerSpecs:                                 {value: InproxyBrokerSpecsValue{}},
+	InproxyProxyBrokerSpecs:                            {value: InproxyBrokerSpecsValue{}},
+	InproxyClientBrokerSpecs:                           {value: InproxyBrokerSpecsValue{}},
 	InproxyReplayBrokerDialParametersTTL:               {value: 24 * time.Hour, minimum: time.Duration(0)},
 	InproxyReplayBrokerUpdateFrequency:                 {value: 5 * time.Minute, minimum: time.Duration(0)},
 	InproxyReplayBrokerDialParametersProbability:       {value: 1.0, minimum: 0.0},
@@ -876,6 +882,8 @@ var defaultParameters = map[string]struct {
 	InproxyDTLSRandomizationProbability:                {value: 0.5, minimum: 0.0},
 	InproxyDataChannelTrafficShapingProbability:        {value: 0.5, minimum: 0.0},
 	InproxyDataChannelTrafficShapingParameters:         {value: InproxyDataChannelTrafficShapingParametersValue{0, 10, 0, 1500, 0, 10, 1, 1500, 0.5}},
+	InproxySTUNServerAddresses:                         {value: []string{}},
+	InproxySTUNServerAddressesRFC5780:                  {value: []string{}},
 	InproxyProxySTUNServerAddresses:                    {value: []string{}},
 	InproxyProxySTUNServerAddressesRFC5780:             {value: []string{}},
 	InproxyClientSTUNServerAddresses:                   {value: []string{}},
@@ -1607,9 +1615,16 @@ func (p ParametersAccessor) String(name string) string {
 	return value
 }
 
-func (p ParametersAccessor) Strings(name string) []string {
+// Strings returns a []string parameter value. If multiple parameter names are
+// specified, the first name with a non-empty value is used.
+func (p ParametersAccessor) Strings(names ...string) []string {
 	value := []string{}
-	p.snapshot.getValue(name, &value)
+	for _, name := range names {
+		p.snapshot.getValue(name, &value)
+		if len(value) > 0 {
+			break
+		}
+	}
 	return value
 }
 
@@ -1963,10 +1978,17 @@ func (p ParametersAccessor) ConjureTransports(name string) protocol.ConjureTrans
 	return value
 }
 
-// InproxyBrokerSpecs returns a InproxyBrokerSpecs parameter value.
-func (p ParametersAccessor) InproxyBrokerSpecs(name string) InproxyBrokerSpecsValue {
+// InproxyBrokerSpecs returns a InproxyBrokerSpecs parameter value. If
+// multiple parameter names are specified, the first name with a non-empty
+// value is used.
+func (p ParametersAccessor) InproxyBrokerSpecs(names ...string) InproxyBrokerSpecsValue {
 	value := InproxyBrokerSpecsValue{}
-	p.snapshot.getValue(name, &value)
+	for _, name := range names {
+		p.snapshot.getValue(name, &value)
+		if len(value) > 0 {
+			break
+		}
+	}
 	return value
 }
 

+ 20 - 0
psiphon/config.go

@@ -952,6 +952,8 @@ type Config struct {
 	InproxyAllowClient                                     *bool
 	InproxyTunnelProtocolSelectionProbability              *float64
 	InproxyBrokerSpecs                                     parameters.InproxyBrokerSpecsValue
+	InproxyClientBrokerSpecs                               parameters.InproxyBrokerSpecsValue
+	InproxyProxyBrokerSpecs                                parameters.InproxyBrokerSpecsValue
 	InproxyReplayBrokerDialParametersTTLSeconds            *int
 	InproxyReplayBrokerUpdateFrequencySeconds              *int
 	InproxyReplayBrokerDialParametersProbability           *float64
@@ -969,6 +971,8 @@ type Config struct {
 	InproxyDTLSRandomizationProbability                    *float64
 	InproxyDataChannelTrafficShapingProbability            *float64
 	InproxyDataChannelTrafficShapingParameters             *parameters.InproxyDataChannelTrafficShapingParametersValue
+	InproxySTUNServerAddresses                             []string
+	InproxySTUNServerAddressesRFC5780                      []string
 	InproxyProxySTUNServerAddresses                        []string
 	InproxyProxySTUNServerAddressesRFC5780                 []string
 	InproxyClientSTUNServerAddresses                       []string
@@ -2316,6 +2320,14 @@ func (config *Config) makeConfigParameters() map[string]interface{} {
 		applyParameters[parameters.InproxyBrokerSpecs] = config.InproxyBrokerSpecs
 	}
 
+	if len(config.InproxyProxyBrokerSpecs) > 0 {
+		applyParameters[parameters.InproxyProxyBrokerSpecs] = config.InproxyProxyBrokerSpecs
+	}
+
+	if len(config.InproxyClientBrokerSpecs) > 0 {
+		applyParameters[parameters.InproxyClientBrokerSpecs] = config.InproxyClientBrokerSpecs
+	}
+
 	if config.InproxyReplayBrokerDialParametersTTLSeconds != nil {
 		applyParameters[parameters.InproxyReplayBrokerDialParametersTTL] = fmt.Sprintf("%ds", *config.InproxyReplayBrokerDialParametersTTLSeconds)
 	}
@@ -2384,6 +2396,14 @@ func (config *Config) makeConfigParameters() map[string]interface{} {
 		applyParameters[parameters.InproxyDataChannelTrafficShapingParameters] = *config.InproxyDataChannelTrafficShapingParameters
 	}
 
+	if len(config.InproxySTUNServerAddresses) > 0 {
+		applyParameters[parameters.InproxySTUNServerAddresses] = config.InproxySTUNServerAddresses
+	}
+
+	if len(config.InproxySTUNServerAddressesRFC5780) > 0 {
+		applyParameters[parameters.InproxySTUNServerAddressesRFC5780] = config.InproxySTUNServerAddressesRFC5780
+	}
+
 	if len(config.InproxyProxySTUNServerAddresses) > 0 {
 		applyParameters[parameters.InproxyProxySTUNServerAddresses] = config.InproxyProxySTUNServerAddresses
 	}

+ 11 - 3
psiphon/controller.go

@@ -2528,7 +2528,8 @@ func (controller *Controller) runInproxyProxy() {
 			// become available, which is sufficient for the test but is not
 			// as robust as awaiting fresh tactics.
 
-			if !controller.inproxyAwaitBrokerSpecs() {
+			isProxy := true
+			if !controller.inproxyAwaitBrokerSpecs(isProxy) {
 				// Controller is shutting down
 				return
 			}
@@ -2608,14 +2609,21 @@ func (controller *Controller) runInproxyProxy() {
 	NoticeInfo("inproxy proxy: stopped")
 }
 
-func (controller *Controller) inproxyAwaitBrokerSpecs() bool {
+func (controller *Controller) inproxyAwaitBrokerSpecs(isProxy bool) bool {
 
 	ticker := time.NewTicker(100 * time.Millisecond)
 	defer ticker.Stop()
 
 	for {
 		p := controller.config.GetParameters().Get()
-		brokerSpecs := p.InproxyBrokerSpecs(parameters.InproxyBrokerSpecs)
+		var brokerSpecs parameters.InproxyBrokerSpecsValue
+		if isProxy {
+			brokerSpecs = p.InproxyBrokerSpecs(
+				parameters.InproxyProxyBrokerSpecs, parameters.InproxyBrokerSpecs)
+		} else {
+			brokerSpecs = p.InproxyBrokerSpecs(
+				parameters.InproxyClientBrokerSpecs, parameters.InproxyBrokerSpecs)
+		}
 		p.Close()
 
 		if len(brokerSpecs) > 0 {

+ 18 - 9
psiphon/inproxy.go

@@ -221,8 +221,14 @@ func NewInproxyBrokerClientInstance(
 	// Select the broker to use, optionally favoring brokers with replay
 	// data.
 
-	brokerSpecs := p.InproxyBrokerSpecs(parameters.InproxyBrokerSpecs)
-
+	var brokerSpecs parameters.InproxyBrokerSpecsValue
+	if isProxy {
+		brokerSpecs = p.InproxyBrokerSpecs(
+			parameters.InproxyProxyBrokerSpecs, parameters.InproxyBrokerSpecs)
+	} else {
+		brokerSpecs = p.InproxyBrokerSpecs(
+			parameters.InproxyClientBrokerSpecs, parameters.InproxyBrokerSpecs)
+	}
 	if len(brokerSpecs) == 0 {
 		return nil, errors.TraceNew("no broker specs")
 	}
@@ -1635,20 +1641,23 @@ func MakeInproxySTUNDialParameters(
 	p parameters.ParametersAccessor,
 	isProxy bool) (*InproxySTUNDialParameters, error) {
 
-	stunServerAddressesParam := parameters.InproxyClientSTUNServerAddresses
-	stunServerAddressesRFC5780Param := parameters.InproxyClientSTUNServerAddressesRFC5780
+	var stunServerAddresses, stunServerAddressesRFC5780 []string
 	if isProxy {
-		stunServerAddressesParam = parameters.InproxyProxySTUNServerAddresses
-		stunServerAddressesRFC5780Param = parameters.InproxyProxySTUNServerAddressesRFC5780
+		stunServerAddresses = p.Strings(
+			parameters.InproxyProxySTUNServerAddresses, parameters.InproxySTUNServerAddresses)
+		stunServerAddressesRFC5780 = p.Strings(
+			parameters.InproxyProxySTUNServerAddressesRFC5780, parameters.InproxySTUNServerAddressesRFC5780)
+	} else {
+		stunServerAddresses = p.Strings(
+			parameters.InproxyClientSTUNServerAddresses, parameters.InproxySTUNServerAddresses)
+		stunServerAddressesRFC5780 = p.Strings(
+			parameters.InproxyClientSTUNServerAddressesRFC5780, parameters.InproxySTUNServerAddressesRFC5780)
 	}
 
 	// Empty STUN server address lists are not an error condition. When used
 	// for WebRTC, the STUN ICE candidate gathering will be skipped but the
 	// WebRTC connection may still be established via other candidate types.
 
-	stunServerAddresses := p.Strings(stunServerAddressesParam)
-	stunServerAddressesRFC5780 := p.Strings(stunServerAddressesRFC5780Param)
-
 	var stunServerAddress, stunServerAddressRFC5780 string
 
 	if len(stunServerAddresses) > 0 {

+ 61 - 17
psiphon/server/server_test.go

@@ -361,6 +361,7 @@ func TestInproxyOSSH(t *testing.T) {
 			doTunneledNTPRequest: true,
 			doDanglingTCPConn:    true,
 			doLogHostProvider:    true,
+			doTargetBrokerSpecs:  true,
 		})
 }
 
@@ -610,6 +611,7 @@ type runServerConfig struct {
 	doLogHostProvider    bool
 	inspectFlows         bool
 	doSteeringIP         bool
+	doTargetBrokerSpecs  bool
 }
 
 var (
@@ -661,6 +663,7 @@ func runServer(t *testing.T, runConfig *runServerConfig) {
 		var err error
 		inproxyTestConfig, err = generateInproxyTestConfig(
 			addMeekServerForBroker,
+			runConfig.doTargetBrokerSpecs,
 			brokerIPAddress,
 			brokerPort,
 			serverEntrySignaturePublicKey)
@@ -3207,6 +3210,7 @@ type inproxyTestConfig struct {
 
 func generateInproxyTestConfig(
 	addMeekServerForBroker bool,
+	doTargetBrokerSpecs bool,
 	brokerIPAddress string,
 	brokerPort int,
 	serverEntrySignaturePublicKey string) (*inproxyTestConfig, error) {
@@ -3290,12 +3294,11 @@ func generateInproxyTestConfig(
 	}
 	proxySessionPublicKeyCurve25519Str := proxySessionPublicKeyCurve25519.String()
 
-	tacticsParametersJSONFormat := `
-            "InproxyAllowProxy": true,
-            "InproxyAllowClient": true,
-            "InproxyTunnelProtocolSelectionProbability": 1.0,
-            "InproxyAllBrokerPublicKeys": ["%s"],
-            "InproxyBrokerSpecs": [{
+	address := net.JoinHostPort(brokerIPAddress, strconv.Itoa(brokerPort))
+	addressRegex := strings.ReplaceAll(address, ".", "\\\\.")
+
+	brokerSpecsJSONFormat := `
+            [{
                 "BrokerPublicKey": "%s",
                 "BrokerRootObfuscationSecret": "%s",
                 "BrokerFrontingSpecs": [{
@@ -3306,7 +3309,54 @@ func generateInproxyTestConfig(
                     "VerifyPins": ["%s"],
                     "Host": "%s"
                 }]
-            }],
+            }]
+    `
+
+	validBrokerSpecsJSON := fmt.Sprintf(
+		brokerSpecsJSONFormat,
+		brokerSessionPublicKeyStr,
+		brokerRootObfuscationSecretStr,
+		brokerFrontingProviderID,
+		addressRegex,
+		brokerFrontingHostName,
+		brokerVerifyPin,
+		brokerFrontingHostName)
+
+	otherSessionPrivateKey, _ := inproxy.GenerateSessionPrivateKey()
+	otherSessionPublicKey, _ := otherSessionPrivateKey.GetPublicKey()
+	otherRootObfuscationSecret, _ := inproxy.GenerateRootObfuscationSecret()
+
+	invalidBrokerSpecsJSON := fmt.Sprintf(
+		brokerSpecsJSONFormat,
+		otherSessionPublicKey.String(),
+		otherRootObfuscationSecret.String(),
+		prng.HexString(16),
+		prng.HexString(16),
+		prng.HexString(16),
+		prng.HexString(16),
+		prng.HexString(16))
+
+	var brokerSpecsJSON, proxyBrokerSpecsJSON, clientBrokerSpecsJSON string
+	if doTargetBrokerSpecs {
+		// invalidBrokerSpecsJSON should be ignored when specific proxy/client
+		// broker specs are set.
+		brokerSpecsJSON = invalidBrokerSpecsJSON
+		proxyBrokerSpecsJSON = validBrokerSpecsJSON
+		clientBrokerSpecsJSON = validBrokerSpecsJSON
+	} else {
+		brokerSpecsJSON = validBrokerSpecsJSON
+		proxyBrokerSpecsJSON = "[]"
+		clientBrokerSpecsJSON = "[]"
+	}
+
+	tacticsParametersJSONFormat := `
+            "InproxyAllowProxy": true,
+            "InproxyAllowClient": true,
+            "InproxyTunnelProtocolSelectionProbability": 1.0,
+            "InproxyAllBrokerPublicKeys": ["%s", "%s"],
+            "InproxyBrokerSpecs": %s,
+            "InproxyProxyBrokerSpecs": %s,
+            "InproxyClientBrokerSpecs": %s,
             "InproxyAllCommonCompartmentIDs": ["%s"],
             "InproxyCommonCompartmentIDs": ["%s"],
             "InproxyClientDiscoverNATProbability": 0.0,
@@ -3315,19 +3365,13 @@ func generateInproxyTestConfig(
             "InproxyDisableIPv6ICECandidates": true,
     `
 
-	address := net.JoinHostPort(brokerIPAddress, strconv.Itoa(brokerPort))
-	addressRegex := strings.ReplaceAll(address, ".", "\\\\.")
-
 	tacticsParametersJSON := fmt.Sprintf(
 		tacticsParametersJSONFormat,
 		brokerSessionPublicKeyStr,
-		brokerSessionPublicKeyStr,
-		brokerRootObfuscationSecretStr,
-		brokerFrontingProviderID,
-		addressRegex,
-		brokerFrontingHostName,
-		brokerVerifyPin,
-		brokerFrontingHostName,
+		otherSessionPublicKey.String(),
+		brokerSpecsJSON,
+		proxyBrokerSpecsJSON,
+		clientBrokerSpecsJSON,
 		commonCompartmentIDStr,
 		commonCompartmentIDStr)