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

More protocol changes

- Add ObfuscatedSSHAlgorithms configuration

- Fix: randomize server host key algos in SSH KEX
Rod Hynes 7 лет назад
Родитель
Сommit
e87df74db9
4 измененных файлов с 46 добавлено и 22 удалено
  1. 14 9
      psiphon/common/crypto/ssh/handshake.go
  2. 14 2
      psiphon/config.go
  3. 1 1
      psiphon/server/tunnelServer.go
  4. 17 10
      psiphon/tunnel.go

+ 14 - 9
psiphon/common/crypto/ssh/handshake.go

@@ -482,7 +482,7 @@ func (t *handshakeTransport) sendKexInit() error {
 	//
 	if t.remoteAddr != nil {
 
-		transform := func(list []string) []string {
+		transform := func(list []string, doCut bool) []string {
 
 			newList := make([]string, len(list))
 			perm, err := common.MakeSecureRandomPerm(len(list))
@@ -492,23 +492,28 @@ func (t *handshakeTransport) sendKexInit() error {
 				}
 			}
 
-			cut := len(newList)
-			for ; cut > 1; cut-- {
-				if !common.FlipCoin() {
-					break
+			if doCut {
+				cut := len(newList)
+				for ; cut > 1; cut-- {
+					if !common.FlipCoin() {
+						break
+					}
 				}
+				newList = newList[:cut]
 			}
 
-			return newList[:cut]
+			return newList
 		}
 
-		msg.KexAlgos = transform(t.config.KeyExchanges)
-		ciphers := transform(t.config.Ciphers)
+		msg.KexAlgos = transform(t.config.KeyExchanges, true)
+		ciphers := transform(t.config.Ciphers, true)
 		msg.CiphersClientServer = ciphers
 		msg.CiphersServerClient = ciphers
-		MACs := transform(t.config.MACs)
+		MACs := transform(t.config.MACs, true)
 		msg.MACsClientServer = MACs
 		msg.MACsServerClient = MACs
+		msg.ServerHostKeyAlgos = transform(
+			msg.ServerHostKeyAlgos, len(t.hostKeys) == 0)
 
 		// Offer "zlib@openssh.com", which is offered by OpenSSH.
 		// Since server only supports "none", must always offer "none"

+ 14 - 2
psiphon/config.go

@@ -461,8 +461,14 @@ type Config struct {
 	FragmentorMaxWriteBytes        *int
 	FragmentorMinDelayMicroseconds *int
 	FragmentorMaxDelayMicroseconds *int
-	ObfuscatedSSHMinPadding        *int
-	ObfuscatedSSHMaxPadding        *int
+
+	// ObfuscatedSSHAlgorithms and associated ObfuscatedSSH fields are for
+	// testing purposes. If specified, ObfuscatedSSHAlgorithms must have 4 SSH
+	// KEX elements in order: the kex algorithm, cipher, MAC, and server host
+	// key algorithm.
+	ObfuscatedSSHAlgorithms []string
+	ObfuscatedSSHMinPadding *int
+	ObfuscatedSSHMaxPadding *int
 
 	// clientParameters is the active ClientParameters with defaults, config
 	// values, and, optionally, tactics applied.
@@ -646,6 +652,12 @@ func (config *Config) Commit() error {
 		return common.ContextError(err)
 	}
 
+	if config.ObfuscatedSSHAlgorithms != nil &&
+		len(config.ObfuscatedSSHAlgorithms) != 4 {
+		// TODO: validate each algorithm?
+		return common.ContextError(errors.New("invalid ObfuscatedSSHAlgorithms"))
+	}
+
 	// clientParameters.Set will validate the config fields applied to parameters.
 
 	err = config.SetClientParameters("", false, nil)

+ 1 - 1
psiphon/server/tunnelServer.go

@@ -1033,7 +1033,7 @@ func (sshClient *sshClient) run(
 		}
 		sshServerConfig.AddHostKey(sshClient.sshServer.sshHostKey)
 
-		if sshClient.tunnelProtocol != protocol.TUNNEL_PROTOCOL_SSH {
+		if protocol.TunnelProtocolUsesObfuscatedSSH(sshClient.tunnelProtocol) {
 			// This is the list of supported non-Encrypt-then-MAC algorithms from
 			// https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/3ef11effe6acd92c3aefd140ee09c42a1f15630b/psiphon/common/crypto/ssh/common.go#L60
 			//

+ 17 - 10
psiphon/tunnel.go

@@ -1029,16 +1029,23 @@ func dialSsh(
 		ClientVersion:   SSHClientVersion,
 	}
 
-	// This is the list of supported non-Encrypt-then-MAC algorithms from
-	// https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/3ef11effe6acd92c3aefd140ee09c42a1f15630b/psiphon/common/crypto/ssh/common.go#L60
-	//
-	// With Encrypt-then-MAC algorithms, packet length is transmitted in
-	// plaintext, which aids in traffic analysis.
-	//
-	// TUNNEL_PROTOCOL_SSH is excepted since its KEX appears in plaintext,
-	// and the protocol is intended to look like SSH on the wire.
-	if selectedProtocol != protocol.TUNNEL_PROTOCOL_SSH {
-		sshClientConfig.MACs = []string{"hmac-sha2-256", "hmac-sha1", "hmac-sha1-96"}
+	if protocol.TunnelProtocolUsesObfuscatedSSH(selectedProtocol) {
+		if config.ObfuscatedSSHAlgorithms != nil {
+			sshClientConfig.KeyExchanges = []string{config.ObfuscatedSSHAlgorithms[0]}
+			sshClientConfig.Ciphers = []string{config.ObfuscatedSSHAlgorithms[1]}
+			sshClientConfig.MACs = []string{config.ObfuscatedSSHAlgorithms[2]}
+			sshClientConfig.HostKeyAlgorithms = []string{config.ObfuscatedSSHAlgorithms[3]}
+		} else {
+			// This is the list of supported non-Encrypt-then-MAC algorithms from
+			// https://github.com/Psiphon-Labs/psiphon-tunnel-core/blob/3ef11effe6acd92c3aefd140ee09c42a1f15630b/psiphon/common/crypto/ssh/common.go#L60
+			//
+			// With Encrypt-then-MAC algorithms, packet length is transmitted in
+			// plaintext, which aids in traffic analysis.
+			//
+			// TUNNEL_PROTOCOL_SSH is excepted since its KEX appears in plaintext,
+			// and the protocol is intended to look like SSH on the wire.
+			sshClientConfig.MACs = []string{"hmac-sha2-256", "hmac-sha1", "hmac-sha1-96"}
+		}
 	}
 
 	// The ssh session establishment (via ssh.NewClientConn) is wrapped