From ab471db32aa83d05f259b660f06552125b3521a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Wed, 29 Nov 2023 11:44:16 +0100 Subject: [PATCH] Use host key checking outside localhost MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verify ssh host keys, when connecting to a remote server. The first connection will prompt, if not in known_hosts. Signed-off-by: Anders F Björklund --- cmd/limactl/copy.go | 10 ++++++++-- cmd/limactl/shell.go | 2 +- cmd/limactl/show_ssh.go | 2 +- pkg/hostagent/hostagent.go | 2 +- pkg/sshutil/sshutil.go | 18 ++++++++++++------ 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/cmd/limactl/copy.go b/cmd/limactl/copy.go index 2cb9be8aa96e..335d71200a79 100644 --- a/cmd/limactl/copy.go +++ b/cmd/limactl/copy.go @@ -51,6 +51,7 @@ func copyAction(cmd *cobra.Command, args []string) error { if err != nil { return err } + instAddr := "127.0.0.1" instDirs := make(map[string]string) scpFlags := []string{} scpArgs := []string{} @@ -68,6 +69,7 @@ func copyAction(cmd *cobra.Command, args []string) error { if sshutil.DetectOpenSSHVersion().LessThan(*semver.New("8.0.0")) { legacySSH = true } + localhostOnly := true for _, arg := range args { path := strings.Split(arg, ":") switch len(path) { @@ -91,6 +93,10 @@ func copyAction(cmd *cobra.Command, args []string) error { } else { scpArgs = append(scpArgs, fmt.Sprintf("scp://%s@%s:%d/%s", u.Username, inst.SSHAddress, inst.SSHLocalPort, path[1])) } + if inst.SSHAddress != "127.0.0.1" { + instAddr = inst.SSHAddress + localhostOnly = false + } instDirs[instName] = inst.Dir default: return fmt.Errorf("path %q contains multiple colons", arg) @@ -108,14 +114,14 @@ func copyAction(cmd *cobra.Command, args []string) error { // arguments such as ControlPath. This is preferred as we can multiplex // sessions without re-authenticating (MaxSessions permitting). for _, instDir := range instDirs { - sshOpts, err = sshutil.SSHOpts(instDir, false, false, false, false) + sshOpts, err = sshutil.SSHOpts(instDir, false, instAddr, false, false, false) if err != nil { return err } } } else { // Copying among multiple hosts; we can't pass in host-specific options. - sshOpts, err = sshutil.CommonOpts(false) + sshOpts, err = sshutil.CommonOpts(false, localhostOnly) if err != nil { return err } diff --git a/cmd/limactl/shell.go b/cmd/limactl/shell.go index d48be1a38e61..ac43d051656f 100644 --- a/cmd/limactl/shell.go +++ b/cmd/limactl/shell.go @@ -168,7 +168,7 @@ func shellAction(cmd *cobra.Command, args []string) error { } } - sshOpts, err := sshutil.SSHOpts(inst.Dir, *y.SSH.LoadDotSSHPubKeys, *y.SSH.ForwardAgent, *y.SSH.ForwardX11, *y.SSH.ForwardX11Trusted) + sshOpts, err := sshutil.SSHOpts(inst.Dir, *y.SSH.LoadDotSSHPubKeys, *y.SSH.Address, *y.SSH.ForwardAgent, *y.SSH.ForwardX11, *y.SSH.ForwardX11Trusted) if err != nil { return err } diff --git a/cmd/limactl/show_ssh.go b/cmd/limactl/show_ssh.go index 7e56fb18ff98..f6a8004cd817 100644 --- a/cmd/limactl/show_ssh.go +++ b/cmd/limactl/show_ssh.go @@ -91,7 +91,7 @@ func showSSHAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - opts, err := sshutil.SSHOpts(inst.Dir, *y.SSH.LoadDotSSHPubKeys, *y.SSH.ForwardAgent, *y.SSH.ForwardX11, *y.SSH.ForwardX11Trusted) + opts, err := sshutil.SSHOpts(inst.Dir, *y.SSH.LoadDotSSHPubKeys, *y.SSH.Address, *y.SSH.ForwardAgent, *y.SSH.ForwardX11, *y.SSH.ForwardX11Trusted) if err != nil { return err } diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index 06878fa5d0c8..2b9a99c52bbb 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -135,7 +135,7 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt return nil, err } - sshOpts, err := sshutil.SSHOpts(inst.Dir, *y.SSH.LoadDotSSHPubKeys, *y.SSH.ForwardAgent, *y.SSH.ForwardX11, *y.SSH.ForwardX11Trusted) + sshOpts, err := sshutil.SSHOpts(inst.Dir, *y.SSH.LoadDotSSHPubKeys, *y.SSH.Address, *y.SSH.ForwardAgent, *y.SSH.ForwardX11, *y.SSH.ForwardX11Trusted) if err != nil { return nil, err } diff --git a/pkg/sshutil/sshutil.go b/pkg/sshutil/sshutil.go index 1ad37ec57d55..3fdca9f6a992 100644 --- a/pkg/sshutil/sshutil.go +++ b/pkg/sshutil/sshutil.go @@ -125,7 +125,7 @@ var sshInfo struct { // // The result always contains the IdentityFile option. // The result never contains the Port option. -func CommonOpts(useDotSSH bool) ([]string, error) { +func CommonOpts(useDotSSH, localhost bool) ([]string, error) { configDir, err := dirnames.LimaConfigDir() if err != nil { return nil, err @@ -180,14 +180,20 @@ func CommonOpts(useDotSSH bool) ([]string, error) { } } + if localhost { + opts = append(opts, + "StrictHostKeyChecking=no", + "UserKnownHostsFile=/dev/null", + "BatchMode=yes", + ) + } + opts = append(opts, - "StrictHostKeyChecking=no", - "UserKnownHostsFile=/dev/null", "NoHostAuthenticationForLocalhost=yes", "GSSAPIAuthentication=no", "PreferredAuthentications=publickey", "Compression=no", - "BatchMode=yes", + "PasswordAuthentication=no", "IdentitiesOnly=yes", ) @@ -222,7 +228,7 @@ func CommonOpts(useDotSSH bool) ([]string, error) { } // SSHOpts adds the following options to CommonOptions: User, ControlMaster, ControlPath, ControlPersist -func SSHOpts(instDir string, useDotSSH, forwardAgent, forwardX11, forwardX11Trusted bool) ([]string, error) { +func SSHOpts(instDir string, useDotSSH bool, hostAddress string, forwardAgent, forwardX11, forwardX11Trusted bool) ([]string, error) { controlSock := filepath.Join(instDir, filenames.SSHSock) if len(controlSock) >= osutil.UnixPathMax { return nil, fmt.Errorf("socket path %q is too long: >= UNIX_PATH_MAX=%d", controlSock, osutil.UnixPathMax) @@ -231,7 +237,7 @@ func SSHOpts(instDir string, useDotSSH, forwardAgent, forwardX11, forwardX11Trus if err != nil { return nil, err } - opts, err := CommonOpts(useDotSSH) + opts, err := CommonOpts(useDotSSH, hostAddress == "127.0.0.1") if err != nil { return nil, err }