Amir Khan 2 лет назад
Родитель
Сommit
a3235f1ae9

+ 1 - 1
psiphon/common/fragmentor/fragmentor.go

@@ -274,7 +274,7 @@ func (c *Conn) GetReplay() (*prng.Seed, bool) {
 }
 
 // Stops the fragmentor from fragmenting any further writes.
-func (c *Conn) Stop() {
+func (c *Conn) StopFragmenting() {
 
 	c.writeMutex.Lock()
 	defer c.writeMutex.Unlock()

+ 1 - 1
psiphon/common/net.go

@@ -77,7 +77,7 @@ type UnderlyingTCPAddrSource interface {
 type FragmentorAccessor interface {
 	SetReplay(*prng.PRNG)
 	GetReplay() (*prng.Seed, bool)
-	Stop()
+	StopFragmenting()
 }
 
 // HTTPRoundTripper is an adapter that allows using a function as a

+ 26 - 7
psiphon/common/obfuscator/obfuscatedSshConn.go

@@ -178,11 +178,10 @@ func NewObfuscatedSSHConn(
 		// NewServerObfuscator reads a seed message from conn
 		obfuscator, err = NewServerObfuscator(
 			&ObfuscatorConfig{
-				Keyword:               obfuscationKeyword,
-				ServerPrefixSpecs:     serverPrefixSepcs,
-				OSSHPrefixSplitConfig: osshPrefixSplitConfig,
-				SeedHistory:           seedHistory,
-				IrregularLogger:       irregularLogger,
+				Keyword:           obfuscationKeyword,
+				ServerPrefixSpecs: serverPrefixSepcs,
+				SeedHistory:       seedHistory,
+				IrregularLogger:   irregularLogger,
 			},
 			common.IPAddressFromAddr(conn.RemoteAddr()),
 			conn)
@@ -259,7 +258,6 @@ func NewServerObfuscatedSSHConn(
 	obfuscationKeyword string,
 	seedHistory *SeedHistory,
 	serverPrefixSpecs transforms.Specs,
-	osshPrefixSplitConfig *OSSHPrefixSplitConfig,
 	irregularLogger func(
 		clientIP string,
 		err error,
@@ -272,7 +270,7 @@ func NewServerObfuscatedSSHConn(
 		nil, nil,
 		nil,
 		serverPrefixSpecs,
-		osshPrefixSplitConfig,
+		nil,
 		nil, nil,
 		seedHistory,
 		irregularLogger)
@@ -295,6 +293,27 @@ func (conn *ObfuscatedSSHConn) GetDerivedPRNG(salt string) (*prng.PRNG, error) {
 	return conn.obfuscator.GetDerivedPRNG(salt)
 }
 
+// SetOSSHPrefixSplitConfig sets the OSSHPrefixSplitConfig for the server.
+// This must be called before any data is written.
+func (conn *ObfuscatedSSHConn) SetOSSHPrefixSplitConfig(minDelay, maxDelay time.Duration) error {
+	if conn.mode != OBFUSCATION_CONN_MODE_SERVER {
+		return errors.TraceNew("SetOSSHPrefixSplitConfig() is only valid for server connections")
+	}
+	if conn.writeState != OBFUSCATION_WRITE_STATE_SERVER_SEND_PREFIX_AND_IDENTIFICATION_LINE_PADDING {
+		return errors.TraceNew("SetOSSHPrefixSplitConfig() must be called before any data is written")
+	}
+	seed, err := conn.obfuscator.GetDerivedPRNGSeed("obfuscated-ssh-prefix-split")
+	if err != nil {
+		return errors.Trace(err)
+	}
+	conn.obfuscator.osshPrefixSplitConfig = &OSSHPrefixSplitConfig{
+		Seed:     seed,
+		MinDelay: minDelay,
+		MaxDelay: maxDelay,
+	}
+	return nil
+}
+
 // GetMetrics implements the common.MetricsSource interface.
 func (conn *ObfuscatedSSHConn) GetMetrics() common.LogFields {
 	logFields := make(common.LogFields)

+ 14 - 1
psiphon/common/obfuscator/obfuscator.go

@@ -256,7 +256,20 @@ func NewServerObfuscator(
 // client, so derived PRNGs may be used to replay sequences post-initial
 // obfuscator message.
 func (obfuscator *Obfuscator) GetDerivedPRNG(salt string) (*prng.PRNG, error) {
-	return prng.NewPRNGWithSaltedSeed(obfuscator.paddingPRNGSeed, salt)
+	seed, err := prng.NewPRNGWithSaltedSeed(obfuscator.paddingPRNGSeed, salt)
+	return seed, errors.Trace(err)
+}
+
+// GetDerivedPRNGSeed creates a new PRNG seed derived from the obfuscator
+// padding seed and distinguished by the salt, which should be a unique
+// identifier for each usage context.
+//
+// For NewServerObfuscator, the obfuscator padding seed is obtained from the
+// client, so derived seeds may be used to replay sequences post-initial
+// obfuscator message.
+func (obfuscator *Obfuscator) GetDerivedPRNGSeed(salt string) (*prng.Seed, error) {
+	seed, err := prng.NewSaltedSeed(obfuscator.paddingPRNGSeed, salt)
+	return seed, errors.Trace(err)
 }
 
 // GetPaddingLength returns the client seed message padding length. Only valid

+ 0 - 1
psiphon/common/obfuscator/obfuscator_test.go

@@ -743,7 +743,6 @@ func obfuscatedSSHConnTestHelper(
 				keyword,
 				NewSeedHistory(nil),
 				serverPrefixSpecs,
-				nil,
 				func(_ string, err error, logFields common.LogFields) {
 					t.Logf("IrregularLogger: %s %+v", err, logFields)
 				})

+ 0 - 51
psiphon/common/parameters/obfuscator.go

@@ -1,51 +0,0 @@
-package parameters
-
-import (
-	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
-	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
-	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
-)
-
-func NewOSSHPrefixSpecParameters(p ParametersAccessor, dialPortNumber string) (*obfuscator.OSSHPrefixSpec, error) {
-
-	seed, err := prng.NewSeed()
-	if err != nil {
-		return nil, errors.Trace(err)
-	}
-
-	if !p.WeightedCoinFlip(OSSHPrefixProbability) {
-		return &obfuscator.OSSHPrefixSpec{}, nil
-	}
-
-	specs := p.ProtocolTransformSpecs(OSSHPrefixSpecs)
-	scopedSpecNames := p.ProtocolTransformScopedSpecNames(OSSHPrefixScopedSpecNames)
-
-	name, spec := specs.Select(dialPortNumber, scopedSpecNames)
-
-	if spec == nil {
-		return &obfuscator.OSSHPrefixSpec{}, nil
-	} else {
-		return &obfuscator.OSSHPrefixSpec{
-			Name: name,
-			Spec: spec,
-			Seed: seed,
-		}, nil
-	}
-}
-
-func NewOSSHPrefixSplitConfig(p ParametersAccessor) (*obfuscator.OSSHPrefixSplitConfig, error) {
-
-	seed, err := prng.NewSeed()
-	if err != nil {
-		return nil, errors.Trace(err)
-	}
-
-	minDelay := p.Duration(OSSHPrefixSplitMinDelay)
-	maxDelay := p.Duration(OSSHPrefixSplitMaxDelay)
-
-	return &obfuscator.OSSHPrefixSplitConfig{
-		Seed:     seed,
-		MinDelay: minDelay,
-		MaxDelay: maxDelay,
-	}, nil
-}

+ 47 - 2
psiphon/dialParameters.go

@@ -887,12 +887,12 @@ func MakeDialParameters(
 			if err != nil {
 				return nil, errors.Trace(err)
 			}
-			prefixSpec, err := parameters.NewOSSHPrefixSpecParameters(p, strconv.Itoa(dialPortNumber))
+			prefixSpec, err := makeOSSHPrefixSpecParameters(p, strconv.Itoa(dialPortNumber))
 			if err != nil {
 				return nil, errors.Trace(err)
 			}
 
-			splitConfig, err := parameters.NewOSSHPrefixSplitConfig(p)
+			splitConfig, err := makeOSSHPrefixSplitConfig(p)
 			if err != nil {
 				return nil, errors.Trace(err)
 			}
@@ -1640,3 +1640,48 @@ func makeSeedTransformerParameters(p parameters.ParametersAccessor,
 		}, nil
 	}
 }
+
+func makeOSSHPrefixSpecParameters(
+	p parameters.ParametersAccessor,
+	dialPortNumber string) (*obfuscator.OSSHPrefixSpec, error) {
+
+	if !p.WeightedCoinFlip(parameters.OSSHPrefixProbability) {
+		return &obfuscator.OSSHPrefixSpec{}, nil
+	}
+
+	specs := p.ProtocolTransformSpecs(parameters.OSSHPrefixSpecs)
+	scopedSpecNames := p.ProtocolTransformScopedSpecNames(parameters.OSSHPrefixScopedSpecNames)
+
+	name, spec := specs.Select(dialPortNumber, scopedSpecNames)
+
+	if spec == nil {
+		return &obfuscator.OSSHPrefixSpec{}, nil
+	} else {
+		seed, err := prng.NewSeed()
+		if err != nil {
+			return nil, errors.Trace(err)
+		}
+		return &obfuscator.OSSHPrefixSpec{
+			Name: name,
+			Spec: spec,
+			Seed: seed,
+		}, nil
+	}
+}
+
+func makeOSSHPrefixSplitConfig(p parameters.ParametersAccessor) (*obfuscator.OSSHPrefixSplitConfig, error) {
+
+	minDelay := p.Duration(parameters.OSSHPrefixSplitMinDelay)
+	maxDelay := p.Duration(parameters.OSSHPrefixSplitMaxDelay)
+
+	seed, err := prng.NewSeed()
+	if err != nil {
+		return nil, errors.Trace(err)
+	}
+
+	return &obfuscator.OSSHPrefixSplitConfig{
+		Seed:     seed,
+		MinDelay: minDelay,
+		MaxDelay: maxDelay,
+	}, nil
+}

+ 5 - 2
psiphon/server/meek.go

@@ -1687,8 +1687,11 @@ func (conn *meekConn) GetReplay() (*prng.Seed, bool) {
 	return nil, false
 }
 
-func (conn *meekConn) Stop() {
-	// No-op
+func (conn *meekConn) StopFragmenting() {
+	fragmentor, ok := conn.firstUnderlyingConn.(common.FragmentorAccessor)
+	if ok {
+		fragmentor.StopFragmenting()
+	}
 }
 
 // pumpReads causes goroutines blocking on meekConn.Read() to read

+ 14 - 11
psiphon/server/tunnelServer.go

@@ -1918,18 +1918,12 @@ func (sshClient *sshClient) run(
 
 			var osshPrefixEnableFragmentor bool = false
 			var serverOsshPrefixSpecs transforms.Specs = nil
-			var serverOsshPrefixSplitConfig *obfuscator.OSSHPrefixSplitConfig = nil
+			var minDelay, maxDelay time.Duration
 			if !p.IsNil() {
 				osshPrefixEnableFragmentor = p.Bool(parameters.OSSHPrefixEnableFragmentor)
 				serverOsshPrefixSpecs = p.ProtocolTransformSpecs(parameters.ServerOSSHPrefixSpecs)
-				serverOsshPrefixSplitConfig, err = parameters.NewOSSHPrefixSplitConfig(p)
-
-				// Log error, but continue.
-				if err != nil {
-					log.WithTraceFields(LogFields{"error": errors.Trace(err)}).Warning(
-						"NewOSSHPrefixSplitConfig failed")
-				}
-
+				minDelay = p.Duration(parameters.OSSHPrefixSplitMinDelay)
+				maxDelay = p.Duration(parameters.OSSHPrefixSplitMaxDelay)
 				// Allow garbage collection.
 				p.Close()
 			}
@@ -1941,7 +1935,6 @@ func (sshClient *sshClient) run(
 				sshClient.sshServer.support.Config.ObfuscatedSSHKey,
 				sshClient.sshServer.obfuscatorSeedHistory,
 				serverOsshPrefixSpecs,
-				serverOsshPrefixSplitConfig,
 				func(clientIP string, err error, logFields common.LogFields) {
 					logIrregularTunnel(
 						sshClient.sshServer.support,
@@ -1958,6 +1951,16 @@ func (sshClient *sshClient) run(
 				conn = result.obfuscatedSSHConn
 			}
 
+			// Set the OSSH prefix split config.
+			if err == nil && result.obfuscatedSSHConn.IsOSSHPrefixStream() {
+				err = result.obfuscatedSSHConn.SetOSSHPrefixSplitConfig(minDelay, maxDelay)
+				// Log error, but continue.
+				if err != nil {
+					log.WithTraceFields(LogFields{"error": errors.Trace(err)}).Warning(
+						"SetOSSHPrefixSplitConfig failed")
+				}
+			}
+
 			// Seed the fragmentor, when present, with seed derived from initial
 			// obfuscator message. See tactics.Listener.Accept. This must preceed
 			// ssh.NewServerConn to ensure fragmentor is seeded before downstream bytes
@@ -1975,7 +1978,7 @@ func (sshClient *sshClient) run(
 
 					// Stops the fragmentor if disabled for prefixed OSSH streams.
 					if !osshPrefixEnableFragmentor && result.obfuscatedSSHConn.IsOSSHPrefixStream() {
-						fragmentor.Stop()
+						fragmentor.StopFragmenting()
 					}
 
 				}