146

Why are there two ways to setup SFTP with OpenSSH and when to use which? Is there any difference between them?

I mean the first one is using a lib from OpenSSH and the second one says "use the internal", so it is also OpenSSH?

Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
Denny Crane
  • 1,643

3 Answers3

171

Both sftp-server and internal-sftp are part of OpenSSH. The sftp-server is a standalone binary. The internal-sftp is just a configuration keyword that tells sshd to use the SFTP server code built-into the sshd, instead of running another process (what would typically be the sftp-server).

The internal-sftp was added much later (OpenSSH 4.9p1 in 2008?) than the standalone sftp-server binary. But it is used in the default configuration file now. The sftp-server is now redundant and is kept probably for backward compatibility only.

I believe there's no reason to use the sftp-server for new installations.


From a functional point of view, the sftp-server and internal-sftp are almost identical. They are built from the same source code.

The main advantage of the internal-sftp is, that it requires no support files when used with ChrootDirectory directive.

Quotes from the sshd_config(5) man page:

  • For Subsystem directive:

    The command sftp-server implements the SFTP file transfer subsystem.

    Alternately the name internal-sftp implements an in-process SFTP server. This may simplify configurations using ChrootDirectory to force a different filesystem root on clients.

  • For ForceCommand directive:

    Specifying a command of internal-sftp will force the use of an in-process SFTP server that requires no support files when used with ChrootDirectory.

  • For ChrootDirectory directive:

    The ChrootDirectory must contain the necessary files and directories to support the user's session. For an interactive session this requires at least a shell, typically sh, and basic /dev nodes such as null, zero, stdin, stdout, stderr, and tty devices. For file transfer sessions using SFTP no additional configuration of the environment is necessary if the in-process sftp-server is used, though sessions which use logging may require /dev/log inside the chroot directory on some operating systems (see sftp-server for details).

Another advantage of the internal-sftp is a performance, as it's not necessary to run a new sub-process for it.


It may seem that the sshd could automatically use the internal-sftp, when it encounters the sftp-server, as the functionality is identical and the internal-sftp has even the above advantages. But there are edge cases, where there are differences.

Few examples:

  • Administrator may rely on a login shell configuration to prevent certain users from logging in. Switching to the internal-sftp would bypass the restriction, as the login shell is no longer involved.

  • Using the sftp-server binary (being a standalone process) you can use some hacks, like running the SFTP under sudo.

  • For SSH-1 (if anyone is still using it), Subsystem directive is not involved at all. An SFTP client using SSH-1 tells the server explicitly, what binary the server should run. So legacy SSH-1 SFTP clients have the sftp-server name hard-coded.

  • 1
    "internal-sftp ... is used in the default configuration file now." No, it's not. From the man pages: "By default no subsystems are defined." From the default config included with the openssh source: Subsystem sftp /usr/libexec/sftp-server. – miken32 Feb 15 '23 at 18:29
  • Here is the argument why sftp-server is the default: https://bugzilla.mindrot.org/show_bug.cgi?id=3397 TL;DR: To separate the memory images, to protect the sshd parent process in case of an error in the SFTP server code. – MichaIng Feb 28 '24 at 20:22
8

There exist alternative SFTP implementations that can be used together with OpenSSH:

ptman
  • 29,022
6

You can lock an authorized_key to the external sftp-server.

command="/usr/libexec/openssh/sftp-server" ssh-rsa AAAA…== user@host.com

When you do, your user can sftp, but cannot scp or ssh:

$ sftp host:/etc/group /tmp
Connecting to host...
Fetching /etc/group to /tmp/group
/etc/group                                    100%  870     0.9KB/s   00:00

Attempting to do anything else will just hang:

$ scp host:/etc/group /tmp
Killed by signal 2.

$ ssh host uptime
Killed by signal 2.

Alas, there is no easy way for a key to be locked to a chroot unless the sshd_config is modified. This would be really cool for a user to be able to do without the intervention of the system manager.

  • 4
    ForceCommand internal-sftp should achieve the same – ptman Jun 09 '16 at 07:13
  • 3
    Handy thing there is that without chroot you can use sshfs host:/home/user/.ssh ~/hackme to edit all those settings back to open access if you change your mind later. – sh1 Sep 23 '17 at 06:15
  • 1
    the more important part of @sh1 's point is that if you're going to lock the user down to only sftp in their own .ssh/authorized_keys file, you'd better make sure to chroot them somewhere that .ssh isn't accessible, or they can just replace their authorized_keys file with something more permissve – erik258 Nov 21 '19 at 14:51
  • chown root:group authorized_keys && chmod 0440 authorized_keys – MichaIng Feb 20 '22 at 13:12
  • 1
    If all you want to do is lock an account to use SFTP only, just give their account the default shell /sbin/nologin – Phx Dec 30 '19 at 13:20
  • @MichaIng That's not safe either, because the user could just rename their .ssh folder to .ssh_old and create a new .ssh folder with a new authorized_keys file of their choice. Unless you also forbid them to change anything in their home directory, which might defeat the point or a home directory in the eyes of some people... – Fritz Feb 19 '24 at 16:24
  • That's true. chmod 0500 .ssh maybe prevents against this. But what Phx says is probably the best approach: To lock the SFTP user into another sub directory via chroot. We use ChrootDirectory and ForceCommand internal-sftp (as described in the accepted answer) and the actual home directory of the SFTP upload user is owned by root with 0711 mode. This effectively locks the SFTP user into the chroot sub directory. – MichaIng Feb 28 '24 at 20:28