sftp: add --sftp-pin-host-key - Trust On First Use host key pinning
Add two new options, pin_host_key and host_keys, that together provide a TOFU host-key validation mode for users who don't maintain a known_hosts file. When --sftp-pin-host-key is used, rclone records the server's host key into host_keys on the first successful connection and verifies it on every subsequent connection. host_keys is always validated when non-empty, so it can also be used by hand to pin a known fingerprint without enabling TOFU writing. known_hosts_file takes precedence if both are set. SSH host certificates are rejected with a clear message pointing at known_hosts_file. On-the-fly remotes log a warning since the captured key cannot be persisted.
This commit is contained in:
+115
-7
@@ -208,15 +208,25 @@ 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.
|
||||
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. Rclone will produce a warning `No host key validation
|
||||
is being performed` each time the backend is started in this mode.
|
||||
|
||||
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.
|
||||
Host key matching, using standard ssh `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. using the OpenSSH `known_hosts` file:
|
||||
Alternatively rclone can maintain server host keys in a `host_keys`
|
||||
setting in the config file. This can be updated automatically with
|
||||
`--sftp-pin-host-key`.
|
||||
|
||||
These options are described below
|
||||
|
||||
### Using the OpenSSH known_hosts file
|
||||
|
||||
Using the OpenSSH `known_hosts` file looks like this:
|
||||
|
||||
```ini
|
||||
[remote]
|
||||
@@ -266,6 +276,104 @@ 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.
|
||||
|
||||
### Host key pinning
|
||||
|
||||
As an alternative to maintaining a `known_hosts` file, rclone supports
|
||||
Trust On First Use (TOFU) host key pinning via the `--sftp-pin-host-key`
|
||||
command-line flag.
|
||||
|
||||
The recommended workflow is:
|
||||
|
||||
1. For the very first connection to a new remote, run rclone once with
|
||||
`--sftp-pin-host-key`. Rclone records the server's host key into the
|
||||
remote's `host_keys` config option and logs the SHA256 fingerprint:
|
||||
|
||||
```console
|
||||
$ rclone --sftp-pin-host-key lsd remote:
|
||||
2026/01/01 12:00:00 NOTICE: sftp://sftpuser@example.com:22/: Accepted ssh-ed25519 host key SHA256:abc... for example.com:22 on first use
|
||||
2026/01/01 12:00:00 NOTICE: sftp://sftpuser@example.com:22/: Pinned ssh-ed25519 host key SHA256:abc... for example.com:22 in config
|
||||
```
|
||||
|
||||
2. For every subsequent run, omit the flag. Rclone consults the pinned
|
||||
`host_keys` and refuses the connection on any mismatch.
|
||||
|
||||
This is a strict improvement over the default of no host key validation,
|
||||
but note that the first connection itself is unauthenticated. Rclone
|
||||
detects later key changes, not a man-in-the-middle who is already on-path
|
||||
the first time you connect. Ideally do the first connection over a trusted
|
||||
network or cross-check the fingerprint rclone logs against one provided out
|
||||
of band by the server operator.
|
||||
|
||||
If `known_hosts_file` is also set it takes precedence and
|
||||
`--sftp-pin-host-key` is ignored.
|
||||
|
||||
After the first successful connection the config will contain a new line:
|
||||
|
||||
```ini
|
||||
[remote]
|
||||
type = sftp
|
||||
host = example.com
|
||||
user = sftpuser
|
||||
pass =
|
||||
host_keys = ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...
|
||||
```
|
||||
|
||||
The `host_keys` field is always validated against the offered host key
|
||||
when non-empty, so you can also pin a known key by hand without ever
|
||||
running with the flag. Each entry is the complete public key - the
|
||||
algorithm and base64 fields of a known_hosts line - not its SHA256
|
||||
fingerprint:
|
||||
|
||||
```console
|
||||
rclone config update remote host_keys "ssh-ed25519 AAAAC3..."
|
||||
```
|
||||
|
||||
Setting `pin_host_key = true` persistently in the config file is not
|
||||
recommended: while it is set, rclone will accept any new host key algorithm
|
||||
the server later presents, widening the trust surface beyond the initial
|
||||
pin. Using `--sftp-pin-host-key` as a one-shot flag keeps each
|
||||
unauthenticated trust event a deliberate decision.
|
||||
|
||||
#### Re-pinning after a legitimate key change
|
||||
|
||||
If the server's host key is legitimately rotated, rclone will refuse the
|
||||
connection with an error containing both the stored and offered SHA256
|
||||
fingerprints. To accept the new key, clear the stored value and re-run once
|
||||
with the flag:
|
||||
|
||||
```console
|
||||
rclone config update remote host_keys ""
|
||||
rclone --sftp-pin-host-key lsd remote:
|
||||
```
|
||||
|
||||
Alternatively edit `host_keys` directly to replace or add the new entry.
|
||||
Multiple entries (separated by commas) are supported.
|
||||
|
||||
#### Limitations
|
||||
|
||||
- If the server uses an `@cert-authority`-signed host certificate,
|
||||
host key pinning cannot validate it (the certificate is re-issued
|
||||
periodically even though the underlying CA is unchanged). Use
|
||||
`known_hosts_file` with an `@cert-authority` entry instead.
|
||||
- On-the-fly remotes (`:sftp,host=...:`) cannot persist the pinned key -
|
||||
rclone will log a warning and re-accept the server key on every run,
|
||||
so the flag only provides first-connect fingerprint logging. Named
|
||||
remotes used with connection string overrides (`remote,port=2022:`)
|
||||
are fine: the pinned key is saved to the remote's config section.
|
||||
- If the `ssh` option is set, the configured ssh program makes the
|
||||
connection and does its own host key validation, so `host_keys` is
|
||||
not consulted and `--sftp-pin-host-key` pins nothing.
|
||||
- Load-balanced SFTP endpoints that present a different host key per
|
||||
backend node will produce a mismatch when a later connection lands on
|
||||
a different node. Re-run with `--sftp-pin-host-key` after clearing
|
||||
`host_keys`, or repeat the first-connect step until each node's key
|
||||
has been observed, appending the additional entries to `host_keys` by
|
||||
hand (comma-separated).
|
||||
- rclone does not yet support OpenSSH's `hostkeys@openssh.com` extension,
|
||||
the non-RFC mechanism that helps clients learn additional host keys
|
||||
during rotation. This is being tracked upstream at
|
||||
https://github.com/golang/go/issues/37245
|
||||
|
||||
### ssh-agent on macOS
|
||||
|
||||
Note that there seem to be various problems with using an ssh-agent on
|
||||
|
||||
Reference in New Issue
Block a user