Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SFTP door and SSH algorithms

An example

[sftp]
listen = "0.0.0.0:2222"
host_keys = ["/etc/craft-file-gate/host_ed25519"]

[server]
max_sessions_per_user = 10

[sftp] is optional: without it, the SFTP door is off.

Create the host key once, before the first start:

ssh-keygen -t ed25519 -f /etc/craft-file-gate/host_ed25519 -N ""

The [sftp] keys

All keys: Reference [sftp]; timeouts: Timeouts.

[sftp.ban], [sftp.rate_limit]: Bans. In [server], shared by all doors: max_sessions_per_user (concurrent sessions of the same name, across all instances with [cluster]), shutdown_grace_period_secs (Shutdown), [server.hidden_stores] (Uploads).

The door advertises the password and publickey methods. It serves only the sftp subsystem, once per connection: no shell, no exec, no port forwarding.

Host keys

TypeFormat
ed25519, ECDSA (P-256, P-384, P-521), RSAOpenSSH (ssh-keygen) or PEM (ssh-keygen -m PEM, PKCS#8)

Each loaded key is reported with its SHA256:... fingerprint, the one that ssh-keygen -l gives and that a client sees on its first connection. GET /admin/config and the Configuration tab of the console give the same ones.

generate_host_key creates the key only if its file is missing, in 0600, and gives its fingerprint. An existing file is read as is: the key does not change from one start to the next. Keep it for a single instance on persistent storage; in Kubernetes, mount a Secret (see Kubernetes secrets).

A table entry chooses the algorithms a key advertises, with the [sftp.algorithms] syntax applied to the host_key list:

[sftp]
listen = "0.0.0.0:2222"
host_keys = [
  "/etc/craft-file-gate/host_ed25519",
  { path = "/etc/craft-file-gate/host_rsa", algorithms = ["rsa-sha2-512", "rsa-sha2-256"] },
]

An algorithm is advertised only if a loaded key can sign with it.

Algorithms

[sftp.algorithms] sets the algorithms offered, per category. Each list starts from a modern default and is edited as in OpenSSH:

SyntaxEffect
["+name"]appends name to the end of the default
["-name"]removes name from the default
["a", "b"]replaces the default with this list

The defaults, list by list: Reference [sftp.algorithms].

  • kex, ciphers, macs and host_key are negotiated before the user is known: they apply to the whole server.
  • user_key gives the algorithms a user key may sign its connection with (OpenSSH’s PubkeyAcceptedAlgorithms). A role can allow others for its own users only (user_key_algorithms, see Authentication).
  • The ext-info-* and kex-strict-* markers are always added to kex.
  • The server-sig-algs extension advertises to the client the host_key list in force, then the user_key algorithms that no host key signs.

Weak algorithms

diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, diffie-hellman-group-exchange-sha1, aes*-cbc, hmac-sha1, hmac-sha1-etm@openssh.com and ssh-rsa (RSA signed with SHA-1) are in no default. Added with +, they are offered. diffie-hellman-group-exchange-sha256 can also be added, outside the default.

An old client

# An old JSch client: neither curve25519 nor ML-KEM
[sftp.algorithms]
kex = ["+diffie-hellman-group14-sha1"]
The client does not knowAdd
curve25519, ML-KEMkex = ["+diffie-hellman-group14-sha1"]
ssh-ed25519 as a host keyan ECDSA P-256 host key in host_keys (ssh-keygen -t ecdsa -b 256 -f host_ecdsa -N ""), rather than an RSA one as ssh-rsa
rsa-sha2-* for its user keyuser_key_algorithms = ["ssh-rsa"] on its role only

The sessions list of the console shows, for each session, the negotiated algorithms and those that are weak (weak_algorithms).

What you will see

WhenLine
startup, each host keyINFO loaded host key, fields path, key_type, fingerprint
startupINFO SSH algorithms offered, fields kex, ciphers, macs, host_key, user_key
connection acceptedINFO new SSH connection
session openedINFO session established and registered, fields session_id, auth_method, signature_algorithm, total_sessions
ordinary end of a connectionINFO SSH session ended: <reason>, fields peer, username, client_version