sftp: Allow user to optionally check server hosts key to add security
Based on Issue 4087 https://github.com/rclone/rclone/issues/4087 Current behaviour is insecure. If the user specifies this value then we switch to validating the server hostkey and so can detect server changes or MITM-type attacks.
This commit is contained in:
parent
66def93373
commit
6dc28ef50a
2 changed files with 89 additions and 0 deletions
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/rclone/rclone/lib/readers"
|
||||
sshagent "github.com/xanzy/ssh-agent"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/knownhosts"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -86,6 +87,16 @@ in the new OpenSSH format can't be used.`,
|
|||
Help: `Optional path to public key file.
|
||||
|
||||
Set this if you have a signed certificate you want to use for authentication.` + env.ShellExpandHelp,
|
||||
}, {
|
||||
Name: "known_hosts_file",
|
||||
Help: `Optional path to known_hosts file.
|
||||
|
||||
Set this value to enable server host key validation.` + env.ShellExpandHelp,
|
||||
Advanced: true,
|
||||
Examples: []fs.OptionExample{{
|
||||
Value: "~/.ssh/known_hosts",
|
||||
Help: "Use OpenSSH's known_hosts file",
|
||||
}},
|
||||
}, {
|
||||
Name: "key_use_agent",
|
||||
Help: `When set forces the usage of the ssh-agent.
|
||||
|
@ -195,6 +206,7 @@ type Options struct {
|
|||
KeyFile string `config:"key_file"`
|
||||
KeyFilePass string `config:"key_file_pass"`
|
||||
PubKeyFile string `config:"pubkey_file"`
|
||||
KnownHostsFile string `config:"known_hosts_file"`
|
||||
KeyUseAgent bool `config:"key_use_agent"`
|
||||
UseInsecureCipher bool `config:"use_insecure_cipher"`
|
||||
DisableHashCheck bool `config:"disable_hashcheck"`
|
||||
|
@ -414,6 +426,7 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
|
|||
if opt.Port == "" {
|
||||
opt.Port = "22"
|
||||
}
|
||||
|
||||
sshConfig := &ssh.ClientConfig{
|
||||
User: opt.User,
|
||||
Auth: []ssh.AuthMethod{},
|
||||
|
@ -422,6 +435,14 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
|
|||
ClientVersion: "SSH-2.0-" + fs.Config.UserAgent,
|
||||
}
|
||||
|
||||
if opt.KnownHostsFile != "" {
|
||||
hostcallback, err := knownhosts.New(opt.KnownHostsFile)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "couldn't parse known_hosts_file")
|
||||
}
|
||||
sshConfig.HostKeyCallback = hostcallback
|
||||
}
|
||||
|
||||
if opt.UseInsecureCipher {
|
||||
sshConfig.Config.SetDefaults()
|
||||
sshConfig.Config.Ciphers = append(sshConfig.Config.Ciphers, "aes128-cbc", "aes192-cbc", "aes256-cbc", "3des-cbc")
|
||||
|
|
|
@ -148,6 +148,57 @@ Note: the cert must come first in the file. e.g.
|
|||
cat id_rsa-cert.pub id_rsa > merged_key
|
||||
```
|
||||
|
||||
### Host key validation ###
|
||||
|
||||
By default rclone will not check the server's host key for validation. This
|
||||
can allow an attacker to replace a server with their own and if you use
|
||||
password authentication then this can lead to that password being exposed.
|
||||
|
||||
Host key matching, using standard `known_hosts` files can be turned on by
|
||||
enabling the `known_hosts_file` option. This can point to the file maintained
|
||||
by `OpenSSH` or can point to a unique file.
|
||||
|
||||
e.g.
|
||||
|
||||
```
|
||||
[remote]
|
||||
type = sftp
|
||||
host = example.com
|
||||
user = sftpuser
|
||||
pass =
|
||||
known_hosts_file = ~/.ssh/known_hosts
|
||||
````
|
||||
|
||||
There are some limitations:
|
||||
|
||||
* `rclone` will not _manage_ this file for you. If the key is missing or
|
||||
wrong then the connection will be refused.
|
||||
* If the server is set up for a certificate host key then the entry in
|
||||
the `known_hosts` file _must_ be the `@cert-authority` entry for the CA
|
||||
* Unlike `OpenSSH`, the libraries used by `rclone` do not permit (at time
|
||||
of writing) multiple host keys to be listed for a server. Only the first
|
||||
entry is used.
|
||||
|
||||
If the host key provided by the server does not match the one in the
|
||||
file (or is missing) then the connection will be aborted and an error
|
||||
returned such as
|
||||
|
||||
NewFs: couldn't connect SSH: ssh: handshake failed: knownhosts: key mismatch
|
||||
|
||||
or
|
||||
|
||||
NewFs: couldn't connect SSH: ssh: handshake failed: knownhosts: key is unknown
|
||||
|
||||
If you see an error such as
|
||||
|
||||
NewFs: couldn't connect SSH: ssh: handshake failed: ssh: no authorities for hostname: example.com:22
|
||||
|
||||
then it is likely the server has presented a CA signed host certificate
|
||||
and you will need to add the appropriate `@cert-authority` entry.
|
||||
|
||||
The `known_hosts_file` setting can be set during `rclone config` as an
|
||||
advanced option.
|
||||
|
||||
### ssh-agent on macOS ###
|
||||
|
||||
Note that there seem to be various problems with using an ssh-agent on
|
||||
|
@ -320,6 +371,23 @@ Leave blank or set to false to enable hashing (recommended), set to true to disa
|
|||
|
||||
Here are the advanced options specific to sftp (SSH/SFTP Connection).
|
||||
|
||||
#### --sftp-known-hosts-file
|
||||
|
||||
Optional path to known_hosts file.
|
||||
|
||||
Set this value to enable server host key validation.
|
||||
|
||||
Leading `~` will be expanded in the file name as will environment variables such as `${RCLONE_CONFIG_DIR}`.
|
||||
|
||||
|
||||
- Config: known_hosts_file
|
||||
- Env Var: RCLONE_SFTP_KNOWN_HOSTS_FILE
|
||||
- Type: string
|
||||
- Default: ""
|
||||
- Examples:
|
||||
- "~/.ssh/known_hosts"
|
||||
- Use OpenSSH's known_hosts file
|
||||
|
||||
#### --sftp-ask-password
|
||||
|
||||
Allow asking for SFTP password when needed.
|
||||
|
|
Loading…
Reference in a new issue