Closed abakum closed 3 months ago
Do you have to dial a new connection? How to prevent man-in-the-middle attacks?
Maybe look for the first key in the list of the new dial?
Unless it works without any new connections.
Does OpenSSH do this without new connections?
Does OpenSSH do this without new connections?
Of course. Check https://github.com/golang/go/issues/37245
But look ssh-keyscan -vv ssh-j.com
- it use 5 connection
Maybe give the user a choice? 1) yes
debug: login to [12], addr: 10.161.115.143:12
The authenticity of host '10.161.115.143:12' can't be established.
ecdsa-sha2-nistp256 key fingerprint is SHA256:MgIL01Bxop23VnARGMM0Ouz9ufLRnJb78vLTiUule3M
ssh-ed25519 key fingerprint is SHA256:pr+YBhrI0y822dBXTNoluQ6wULycpQEiGiyZeYU/s2o
ssh-rsa key fingerprint is SHA256:6n4F7GNw8SgLaSavF9sE/1bFCxRgvrDu7p2YYXHN4A8
Are you sure you want to continue connecting (yes/no/all/[fingerprint])? yes
Warning: Permanently added '10.161.115.143:12' (ecdsa-sha2-nistp256) to the list of known hosts.
2) all
debug: login to [12], addr: 10.161.115.143:12
The authenticity of host '10.161.115.143:12' can't be established.
ecdsa-sha2-nistp256 key fingerprint is SHA256:MgIL01Bxop23VnARGMM0Ouz9ufLRnJb78vLTiUule3M
ssh-ed25519 key fingerprint is SHA256:pr+YBhrI0y822dBXTNoluQ6wULycpQEiGiyZeYU/s2o
ssh-rsa key fingerprint is SHA256:6n4F7GNw8SgLaSavF9sE/1bFCxRgvrDu7p2YYXHN4A8
Are you sure you want to continue connecting (yes/no/all/[fingerprint])? all
Warning: Permanently added '10.161.115.143:12' (ssh-ed25519) to the list of known hosts.
Warning: Permanently added '10.161.115.143:12' (ssh-rsa) to the list of known hosts.
Warning: Permanently added '10.161.115.143:12' (ecdsa-sha2-nistp256) to the list of known hosts.
3) Select by fingerprint
debug: login to [12], addr: 10.161.115.143:12
The authenticity of host '10.161.115.143:12' can't be established.
ecdsa-sha2-nistp256 key fingerprint is SHA256:MgIL01Bxop23VnARGMM0Ouz9ufLRnJb78vLTiUule3M
ssh-rsa key fingerprint is SHA256:6n4F7GNw8SgLaSavF9sE/1bFCxRgvrDu7p2YYXHN4A8
ssh-ed25519 key fingerprint is SHA256:pr+YBhrI0y822dBXTNoluQ6wULycpQEiGiyZeYU/s2o
Are you sure you want to continue connecting (yes/no/all/[fingerprint])? SHA256:6n4F7GNw8SgLaSavF9sE/1bFCxRgvrDu7p2YYXHN4A8
Warning: Permanently added '10.161.115.143:12' (ssh-rsa) to the list of known hosts.
addHostKey https://github.com/abakum/dssh/commit/27659300ee79366bce4f1b10f9fa3663566067da
func addHostKey(path, host string, remote net.Addr, key ssh.PublicKey, ask bool) error {
keyNormalizedLine := knownhosts.Line([]string{host}, key)
for _, acceptKey := range acceptHostKeys {
if acceptKey == keyNormalizedLine {
return nil
}
}
if ask {
if sshLoginSuccess.Load() {
fmt.Fprintf(os.Stderr, "\r\n\033[0;31mThe public key of the remote server has changed after login.\033[0m\r\n")
return fmt.Errorf("host key changed")
}
fingerprint := ssh.FingerprintSHA256(key)
fmt.Fprintf(os.Stderr, "The authenticity of host '%s' can't be established.\r\n"+
"%s key fingerprint is %s\r\n", host, key.Type(), fingerprint)
keys := goScanHostKeys(host, key)
// List other keys for select by fingerprint. Without dot at the end for copyPaste.
for _, key := range keys {
fingerprint := ssh.FingerprintSHA256(key)
fmt.Fprintf(os.Stderr,
"%s key fingerprint is %s\r\n", key.Type(), fingerprint)
}
stdin, closer, err := getKeyboardInput()
if err != nil {
return err
}
defer closer()
reader := bufio.NewReader(stdin)
fmt.Fprintf(os.Stderr, "Are you sure you want to continue connecting (yes/no/all/[fingerprint])? ")
readInput:
for {
input, err := reader.ReadString('\n')
if err != nil {
return err
}
input = strings.TrimSpace(input)
for _, keyByFingerprint := range append(keys, key) {
if input == ssh.FingerprintSHA256(keyByFingerprint) {
key = keyByFingerprint
break readInput
}
}
input = strings.ToLower(input)
if input == "yes" {
break
} else if input == "no" {
return fmt.Errorf("host key not trusted")
} else if input == "all" {
for _, otherKey := range keys {
acceptHostKeys = append(acceptHostKeys, knownhosts.Line([]string{host}, otherKey))
if err := writeKnownHost(path, host, remote, otherKey); err != nil {
warning("Failed to add the host to the list of known hosts (%s): %v", path, err)
return nil
}
warning("Permanently added '%s' (%s) to the list of known hosts.", host, otherKey.Type())
}
break
}
fmt.Fprintf(os.Stderr, "Please type 'yes', 'no', 'all' or the fingerprint: ")
}
}
acceptHostKeys = append(acceptHostKeys, keyNormalizedLine)
if err := writeKnownHost(path, host, remote, key); err != nil {
warning("Failed to add the host to the list of known hosts (%s): %v", path, err)
return nil
}
warning("Permanently added '%s' (%s) to the list of known hosts.", host, key.Type())
return nil
}
I don't think dialing another connection is a good idea. If someone really needs it all, just log in once with openssh.
Thanks for your advice. But the user may not understand the risks here and choose yes blindly. Even if the user understands it and will confirm it one by one, I don't want to increase the user's psychological burden because of it.
This behavior can be done in your login.go by adding after the line https://github.com/trzsz/trzsz-ssh/blob/d154d5bba805fa21d36fd0b02a4df6cd4dae374d/tssh/login.go#L234
scanHostKeys:
Will you accept PR?