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

Move obfuscation code to obfuscator package

- This resolves a test code import cycle
Rod Hynes 7 лет назад
Родитель
Сommit
3cccbbdb31

+ 2 - 0
.travis.yml

@@ -12,6 +12,7 @@ script:
 - cd psiphon
 - go test -race -v ./common
 - go test -race -v ./common/accesscontrol
+- go test -race -v ./common/obfuscator
 - go test -race -v ./common/osl
 - go test -race -v ./common/parameters
 - go test -race -v ./common/protocol
@@ -26,6 +27,7 @@ script:
 - go test -race -v
 - go test -v -covermode=count -coverprofile=common.coverprofile ./common
 - go test -v -covermode=count -coverprofile=accesscontrol.coverprofile ./common/accesscontrol
+- go test -v -covermode=count -coverprofile=obfuscator.coverprofile ./common/obfuscator
 - go test -v -covermode=count -coverprofile=osl.coverprofile ./common/osl
 - go test -v -covermode=count -coverprofile=parameters.coverprofile ./common/parameters
 - go test -v -covermode=count -coverprofile=protocol.coverprofile ./common/protocol

+ 31 - 29
psiphon/common/obfuscatedSshConn.go → psiphon/common/obfuscator/obfuscatedSshConn.go

@@ -17,7 +17,7 @@
  *
  */
 
-package common
+package obfuscator
 
 import (
 	"bytes"
@@ -25,6 +25,8 @@ import (
 	"errors"
 	"io"
 	"net"
+
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 )
 
 const (
@@ -116,7 +118,7 @@ func NewObfuscatedSshConn(
 	if mode == OBFUSCATION_CONN_MODE_CLIENT {
 		obfuscator, err = NewClientObfuscator(&ObfuscatorConfig{Keyword: obfuscationKeyword})
 		if err != nil {
-			return nil, ContextError(err)
+			return nil, common.ContextError(err)
 		}
 		readDeobfuscate = obfuscator.ObfuscateServerToClient
 		writeObfuscate = obfuscator.ObfuscateClientToServer
@@ -127,7 +129,7 @@ func NewObfuscatedSshConn(
 			conn, &ObfuscatorConfig{Keyword: obfuscationKeyword})
 		if err != nil {
 			// TODO: readForver() equivalent
-			return nil, ContextError(err)
+			return nil, common.ContextError(err)
 		}
 		readDeobfuscate = obfuscator.ObfuscateClientToServer
 		writeObfuscate = obfuscator.ObfuscateServerToClient
@@ -156,7 +158,7 @@ func (conn *ObfuscatedSshConn) Read(buffer []byte) (int, error) {
 	}
 	n, err := conn.readAndTransform(buffer)
 	if err != nil {
-		err = ContextError(err)
+		err = common.ContextError(err)
 	}
 	return n, err
 }
@@ -169,7 +171,7 @@ func (conn *ObfuscatedSshConn) Write(buffer []byte) (int, error) {
 	}
 	err := conn.transformAndWrite(buffer)
 	if err != nil {
-		return 0, ContextError(err)
+		return 0, common.ContextError(err)
 	}
 	// Reports that we wrote all the bytes
 	// (although we may have buffered some or all)
@@ -227,7 +229,7 @@ func (conn *ObfuscatedSshConn) readAndTransform(buffer []byte) (int, error) {
 				err := readSshIdentificationLine(
 					conn.Conn, conn.readDeobfuscate, conn.readBuffer)
 				if err != nil {
-					return 0, ContextError(err)
+					return 0, common.ContextError(err)
 				}
 				if bytes.HasPrefix(conn.readBuffer.Bytes(), []byte("SSH-")) {
 					break
@@ -243,7 +245,7 @@ func (conn *ObfuscatedSshConn) readAndTransform(buffer []byte) (int, error) {
 			isMsgNewKeys, err := readSshPacket(
 				conn.Conn, conn.readDeobfuscate, conn.readBuffer)
 			if err != nil {
-				return 0, ContextError(err)
+				return 0, common.ContextError(err)
 			}
 			if isMsgNewKeys {
 				nextState = OBFUSCATION_READ_STATE_FLUSH
@@ -254,7 +256,7 @@ func (conn *ObfuscatedSshConn) readAndTransform(buffer []byte) (int, error) {
 		nextState = OBFUSCATION_READ_STATE_FINISHED
 
 	case OBFUSCATION_READ_STATE_FINISHED:
-		return 0, ContextError(errors.New("invalid read state"))
+		return 0, common.ContextError(errors.New("invalid read state"))
 	}
 
 	n, err := conn.readBuffer.Read(buffer)
@@ -262,7 +264,7 @@ func (conn *ObfuscatedSshConn) readAndTransform(buffer []byte) (int, error) {
 		err = nil
 	}
 	if err != nil {
-		return n, ContextError(err)
+		return n, common.ContextError(err)
 	}
 	if conn.readBuffer.Len() == 0 {
 		conn.readState = nextState
@@ -321,18 +323,18 @@ func (conn *ObfuscatedSshConn) transformAndWrite(buffer []byte) error {
 	if conn.writeState == OBFUSCATION_WRITE_STATE_CLIENT_SEND_SEED_MESSAGE {
 		_, err := conn.Conn.Write(conn.obfuscator.SendSeedMessage())
 		if err != nil {
-			return ContextError(err)
+			return common.ContextError(err)
 		}
 		conn.writeState = OBFUSCATION_WRITE_STATE_IDENTIFICATION_LINE
 	} else if conn.writeState == OBFUSCATION_WRITE_STATE_SERVER_SEND_IDENTIFICATION_LINE_PADDING {
 		padding, err := makeServerIdentificationLinePadding()
 		if err != nil {
-			return ContextError(err)
+			return common.ContextError(err)
 		}
 		conn.writeObfuscate(padding)
 		_, err = conn.Conn.Write(padding)
 		if err != nil {
-			return ContextError(err)
+			return common.ContextError(err)
 		}
 		conn.writeState = OBFUSCATION_WRITE_STATE_IDENTIFICATION_LINE
 	}
@@ -357,14 +359,14 @@ func (conn *ObfuscatedSshConn) transformAndWrite(buffer []byte) error {
 		hasMsgNewKeys, err := extractSshPackets(
 			conn.writeBuffer, conn.transformBuffer)
 		if err != nil {
-			return ContextError(err)
+			return common.ContextError(err)
 		}
 		if hasMsgNewKeys {
 			conn.writeState = OBFUSCATION_WRITE_STATE_FINISHED
 		}
 
 	case OBFUSCATION_WRITE_STATE_FINISHED:
-		return ContextError(errors.New("invalid write state"))
+		return common.ContextError(errors.New("invalid write state"))
 	}
 
 	if conn.transformBuffer.Len() > 0 {
@@ -372,7 +374,7 @@ func (conn *ObfuscatedSshConn) transformAndWrite(buffer []byte) error {
 		conn.writeObfuscate(sendData)
 		_, err := conn.Conn.Write(sendData)
 		if err != nil {
-			return ContextError(err)
+			return common.ContextError(err)
 		}
 	}
 
@@ -381,7 +383,7 @@ func (conn *ObfuscatedSshConn) transformAndWrite(buffer []byte) error {
 			// After SSH_MSG_NEWKEYS, any remaining bytes are un-obfuscated
 			_, err := conn.Conn.Write(conn.writeBuffer.Bytes())
 			if err != nil {
-				return ContextError(err)
+				return common.ContextError(err)
 			}
 		}
 		// The buffer memory is no longer used
@@ -403,7 +405,7 @@ func readSshIdentificationLine(
 	for i := 0; i < SSH_MAX_SERVER_LINE_LENGTH; i++ {
 		_, err := io.ReadFull(conn, oneByte[:])
 		if err != nil {
-			return ContextError(err)
+			return common.ContextError(err)
 		}
 		deobfuscate(oneByte[:])
 		readBuffer.WriteByte(oneByte[0])
@@ -413,7 +415,7 @@ func readSshIdentificationLine(
 		}
 	}
 	if !validLine {
-		return ContextError(errors.New("invalid identification line"))
+		return common.ContextError(errors.New("invalid identification line"))
 	}
 	return nil
 }
@@ -431,7 +433,7 @@ func readSshPacket(
 		err = errors.New("unxpected number of bytes read")
 	}
 	if err != nil {
-		return false, ContextError(err)
+		return false, common.ContextError(err)
 	}
 
 	prefix := readBuffer.Bytes()[prefixOffset : prefixOffset+SSH_PACKET_PREFIX_LENGTH]
@@ -439,7 +441,7 @@ func readSshPacket(
 
 	_, _, payloadLength, messageLength, err := getSshPacketPrefix(prefix)
 	if err != nil {
-		return false, ContextError(err)
+		return false, common.ContextError(err)
 	}
 
 	remainingReadLength := messageLength - SSH_PACKET_PREFIX_LENGTH
@@ -449,7 +451,7 @@ func readSshPacket(
 		err = errors.New("unxpected number of bytes read")
 	}
 	if err != nil {
-		return false, ContextError(err)
+		return false, common.ContextError(err)
 	}
 
 	remainingBytes := readBuffer.Bytes()[prefixOffset+SSH_PACKET_PREFIX_LENGTH:]
@@ -468,9 +470,9 @@ func readSshPacket(
 // From the original patch to sshd.c:
 // https://bitbucket.org/psiphon/psiphon-circumvention-system/commits/f40865ce624b680be840dc2432283c8137bd896d
 func makeServerIdentificationLinePadding() ([]byte, error) {
-	paddingLength, err := MakeSecureRandomInt(OBFUSCATE_MAX_PADDING - 2) // 2 = CRLF
+	paddingLength, err := common.MakeSecureRandomInt(OBFUSCATE_MAX_PADDING - 2) // 2 = CRLF
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 	paddingLength += 2
 	padding := make([]byte, paddingLength)
@@ -518,7 +520,7 @@ func extractSshPackets(writeBuffer, transformBuffer *bytes.Buffer) (bool, error)
 		packetLength, paddingLength, payloadLength, messageLength, err := getSshPacketPrefix(
 			writeBuffer.Bytes()[:SSH_PACKET_PREFIX_LENGTH])
 		if err != nil {
-			return false, ContextError(err)
+			return false, common.ContextError(err)
 		}
 
 		if writeBuffer.Len() < messageLength {
@@ -545,14 +547,14 @@ func extractSshPackets(writeBuffer, transformBuffer *bytes.Buffer) (bool, error)
 		if possiblePaddings > 0 {
 
 			// selectedPadding is integer in range [0, possiblePaddings)
-			selectedPadding, err := MakeSecureRandomInt(possiblePaddings)
+			selectedPadding, err := common.MakeSecureRandomInt(possiblePaddings)
 			if err != nil {
-				return false, ContextError(err)
+				return false, common.ContextError(err)
 			}
 			extraPaddingLength := selectedPadding * SSH_PADDING_MULTIPLE
-			extraPadding, err := MakeSecureRandomBytes(extraPaddingLength)
+			extraPadding, err := common.MakeSecureRandomBytes(extraPaddingLength)
 			if err != nil {
-				return false, ContextError(err)
+				return false, common.ContextError(err)
 			}
 
 			setSshPacketPrefix(
@@ -571,7 +573,7 @@ func getSshPacketPrefix(buffer []byte) (int, int, int, int, error) {
 	packetLength := int(binary.BigEndian.Uint32(buffer[0 : SSH_PACKET_PREFIX_LENGTH-1]))
 
 	if packetLength < 1 || packetLength > SSH_MAX_PACKET_LENGTH {
-		return 0, 0, 0, 0, ContextError(errors.New("invalid ssh packet length"))
+		return 0, 0, 0, 0, common.ContextError(errors.New("invalid ssh packet length"))
 	}
 
 	paddingLength := int(buffer[SSH_PACKET_PREFIX_LENGTH-1])

+ 29 - 27
psiphon/common/obfuscator.go → psiphon/common/obfuscator/obfuscator.go

@@ -17,7 +17,7 @@
  *
  */
 
-package common
+package obfuscator
 
 import (
 	"bytes"
@@ -26,6 +26,8 @@ import (
 	"encoding/binary"
 	"errors"
 	"io"
+
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 )
 
 const (
@@ -58,14 +60,14 @@ type ObfuscatorConfig struct {
 func NewClientObfuscator(
 	config *ObfuscatorConfig) (obfuscator *Obfuscator, err error) {
 
-	seed, err := MakeSecureRandomBytes(OBFUSCATE_SEED_LENGTH)
+	seed, err := common.MakeSecureRandomBytes(OBFUSCATE_SEED_LENGTH)
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 
 	clientToServerCipher, serverToClientCipher, err := initObfuscatorCiphers(seed, config)
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 
 	maxPadding := OBFUSCATE_MAX_PADDING
@@ -75,7 +77,7 @@ func NewClientObfuscator(
 
 	seedMessage, err := makeSeedMessage(maxPadding, seed, clientToServerCipher)
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 
 	return &Obfuscator{
@@ -92,7 +94,7 @@ func NewServerObfuscator(
 	clientToServerCipher, serverToClientCipher, err := readSeedMessage(
 		clientReader, config)
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 
 	return &Obfuscator{
@@ -123,22 +125,22 @@ func initObfuscatorCiphers(
 
 	clientToServerKey, err := deriveKey(seed, []byte(config.Keyword), []byte(OBFUSCATE_CLIENT_TO_SERVER_IV))
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 
 	serverToClientKey, err := deriveKey(seed, []byte(config.Keyword), []byte(OBFUSCATE_SERVER_TO_CLIENT_IV))
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 
 	clientToServerCipher, err := rc4.NewCipher(clientToServerKey)
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 
 	serverToClientCipher, err := rc4.NewCipher(serverToClientKey)
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 
 	return clientToServerCipher, serverToClientCipher, nil
@@ -156,37 +158,37 @@ func deriveKey(seed, keyword, iv []byte) ([]byte, error) {
 		digest = h.Sum(nil)
 	}
 	if len(digest) < OBFUSCATE_KEY_LENGTH {
-		return nil, ContextError(errors.New("insufficient bytes for obfuscation key"))
+		return nil, common.ContextError(errors.New("insufficient bytes for obfuscation key"))
 	}
 	return digest[0:OBFUSCATE_KEY_LENGTH], nil
 }
 
 func makeSeedMessage(maxPadding int, seed []byte, clientToServerCipher *rc4.Cipher) ([]byte, error) {
 	// paddingLength is integer in range [0, maxPadding]
-	paddingLength, err := MakeSecureRandomInt(maxPadding + 1)
+	paddingLength, err := common.MakeSecureRandomInt(maxPadding + 1)
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
-	padding, err := MakeSecureRandomBytes(paddingLength)
+	padding, err := common.MakeSecureRandomBytes(paddingLength)
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 	buffer := new(bytes.Buffer)
 	err = binary.Write(buffer, binary.BigEndian, seed)
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 	err = binary.Write(buffer, binary.BigEndian, uint32(OBFUSCATE_MAGIC_VALUE))
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 	err = binary.Write(buffer, binary.BigEndian, uint32(paddingLength))
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 	err = binary.Write(buffer, binary.BigEndian, padding)
 	if err != nil {
-		return nil, ContextError(err)
+		return nil, common.ContextError(err)
 	}
 	seedMessage := buffer.Bytes()
 	clientToServerCipher.XORKeyStream(seedMessage[len(seed):], seedMessage[len(seed):])
@@ -199,18 +201,18 @@ func readSeedMessage(
 	seed := make([]byte, OBFUSCATE_SEED_LENGTH)
 	_, err := io.ReadFull(clientReader, seed)
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 
 	clientToServerCipher, serverToClientCipher, err := initObfuscatorCiphers(seed, config)
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 
 	fixedLengthFields := make([]byte, 8) // 4 bytes each for magic value and padding length
 	_, err = io.ReadFull(clientReader, fixedLengthFields)
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 
 	clientToServerCipher.XORKeyStream(fixedLengthFields, fixedLengthFields)
@@ -220,25 +222,25 @@ func readSeedMessage(
 	var magicValue, paddingLength int32
 	err = binary.Read(buffer, binary.BigEndian, &magicValue)
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 	err = binary.Read(buffer, binary.BigEndian, &paddingLength)
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 
 	if magicValue != OBFUSCATE_MAGIC_VALUE {
-		return nil, nil, ContextError(errors.New("invalid magic value"))
+		return nil, nil, common.ContextError(errors.New("invalid magic value"))
 	}
 
 	if paddingLength < 0 || paddingLength > OBFUSCATE_MAX_PADDING {
-		return nil, nil, ContextError(errors.New("invalid padding length"))
+		return nil, nil, common.ContextError(errors.New("invalid padding length"))
 	}
 
 	padding := make([]byte, paddingLength)
 	_, err = io.ReadFull(clientReader, padding)
 	if err != nil {
-		return nil, nil, ContextError(err)
+		return nil, nil, common.ContextError(err)
 	}
 
 	clientToServerCipher.XORKeyStream(padding, padding)

+ 4 - 3
psiphon/common/obfuscator_test.go → psiphon/common/obfuscator/obfuscator_test.go

@@ -17,7 +17,7 @@
  *
  */
 
-package common
+package obfuscator
 
 import (
 	"bytes"
@@ -28,12 +28,13 @@ import (
 	"testing"
 	"time"
 
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/ssh"
 )
 
 func TestObfuscator(t *testing.T) {
 
-	keyword, _ := MakeRandomStringHex(32)
+	keyword, _ := common.MakeRandomStringHex(32)
 
 	config := &ObfuscatorConfig{
 		Keyword:    keyword,
@@ -75,7 +76,7 @@ func TestObfuscator(t *testing.T) {
 
 func TestObfuscatedSSHConn(t *testing.T) {
 
-	keyword, _ := MakeRandomStringHex(32)
+	keyword, _ := common.MakeRandomStringHex(32)
 
 	serverAddress := "127.0.0.1:2222"
 

+ 5 - 4
psiphon/common/tactics/tactics.go

@@ -170,6 +170,7 @@ import (
 	"github.com/Psiphon-Inc/goarista/monotime"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/nacl/box"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 )
 
@@ -1657,8 +1658,8 @@ func boxPayload(
 		box = bundledBox
 	}
 
-	obfuscator, err := common.NewClientObfuscator(
-		&common.ObfuscatorConfig{
+	obfuscator, err := obfuscator.NewClientObfuscator(
+		&obfuscator.ObfuscatorConfig{
 			Keyword:    string(obfuscatedKey),
 			MaxPadding: TACTICS_PADDING_MAX_SIZE})
 	if err != nil {
@@ -1688,9 +1689,9 @@ func unboxPayload(
 
 	obfuscatedReader := bytes.NewReader(obfuscatedBoxedPayload[:])
 
-	obfuscator, err := common.NewServerObfuscator(
+	obfuscator, err := obfuscator.NewServerObfuscator(
 		obfuscatedReader,
-		&common.ObfuscatorConfig{Keyword: string(obfuscatedKey)})
+		&obfuscator.ObfuscatorConfig{Keyword: string(obfuscatedKey)})
 	if err != nil {
 		return nil, common.ContextError(err)
 	}

+ 10 - 6
psiphon/common/utils_test.go

@@ -40,7 +40,7 @@ func TestGetStringSlice(t *testing.T) {
 
 	var value interface{}
 
-	err = json.Unmarshal(&value)
+	err = json.Unmarshal(j, &value)
 	if err != nil {
 		t.Errorf("json.Unmarshal failed: %s", err)
 	}
@@ -56,16 +56,20 @@ func TestGetStringSlice(t *testing.T) {
 }
 
 func TestMakeSecureRandomPerm(t *testing.T) {
-	for i := 0; i < 1000; i++ {
-		perm, err := MakeSecureRandomPerm(i)
+	for n := 0; n < 1000; n++ {
+		perm, err := MakeSecureRandomPerm(n)
 		if err != nil {
 			t.Errorf("MakeSecureRandomPerm failed: %s", err)
 		}
+		if len(perm) != n {
+			t.Error("unexpected permutation size")
+		}
 		sum := 0
-		for j := 0; j < i; j++ {
-			sum += perm[j]
+		for i := 0; i < n; i++ {
+			sum += perm[i]
 		}
-		if sum != (i*(i+1))/2 {
+		expectedSum := (n * (n - 1)) / 2
+		if sum != expectedSum {
 			t.Error("unexpected permutation")
 		}
 	}

+ 3 - 2
psiphon/meekConn.go

@@ -41,6 +41,7 @@ import (
 	"github.com/Psiphon-Inc/goarista/monotime"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/nacl/box"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
 	"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/tls"
@@ -1258,8 +1259,8 @@ func makeMeekCookie(
 	copy(encryptedCookie[32:], box)
 
 	// Obfuscate the encrypted data
-	obfuscator, err := common.NewClientObfuscator(
-		&common.ObfuscatorConfig{
+	obfuscator, err := obfuscator.NewClientObfuscator(
+		&obfuscator.ObfuscatorConfig{
 			Keyword:    meekObfuscatedKey,
 			MaxPadding: clientParameters.Get().Int(parameters.MeekCookieMaxPadding)})
 	if err != nil {

+ 3 - 2
psiphon/server/meek.go

@@ -40,6 +40,7 @@ import (
 	"github.com/Psiphon-Inc/goarista/monotime"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/nacl/box"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tls"
 )
@@ -909,9 +910,9 @@ func getMeekCookiePayload(support *SupportServices, cookieValue string) ([]byte,
 
 	reader := bytes.NewReader(decodedValue[:])
 
-	obfuscator, err := common.NewServerObfuscator(
+	obfuscator, err := obfuscator.NewServerObfuscator(
 		reader,
-		&common.ObfuscatorConfig{Keyword: support.Config.MeekObfuscatedKey})
+		&obfuscator.ObfuscatorConfig{Keyword: support.Config.MeekObfuscatedKey})
 	if err != nil {
 		return nil, common.ContextError(err)
 	}

+ 3 - 2
psiphon/server/tunnelServer.go

@@ -38,6 +38,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/accesscontrol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/ssh"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/osl"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/tactics"
@@ -1039,8 +1040,8 @@ func (sshClient *sshClient) run(
 		if protocol.TunnelProtocolUsesObfuscatedSSH(sshClient.tunnelProtocol) {
 			// Note: NewObfuscatedSshConn blocks on network I/O
 			// TODO: ensure this won't block shutdown
-			conn, result.err = common.NewObfuscatedSshConn(
-				common.OBFUSCATION_CONN_MODE_SERVER,
+			conn, result.err = obfuscator.NewObfuscatedSshConn(
+				obfuscator.OBFUSCATION_CONN_MODE_SERVER,
 				conn,
 				sshClient.sshServer.support.Config.ObfuscatedSSHKey)
 			if result.err != nil {

+ 3 - 2
psiphon/tunnel.go

@@ -36,6 +36,7 @@ import (
 	"github.com/Psiphon-Inc/goarista/monotime"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/ssh"
+	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
 	"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/tactics"
@@ -968,8 +969,8 @@ func dialSsh(
 	// Add obfuscated SSH layer
 	var sshConn net.Conn = throttledConn
 	if useObfuscatedSsh {
-		sshConn, err = common.NewObfuscatedSshConn(
-			common.OBFUSCATION_CONN_MODE_CLIENT, throttledConn, serverEntry.SshObfuscatedKey)
+		sshConn, err = obfuscator.NewObfuscatedSshConn(
+			obfuscator.OBFUSCATION_CONN_MODE_CLIENT, throttledConn, serverEntry.SshObfuscatedKey)
 		if err != nil {
 			return nil, common.ContextError(err)
 		}