0
  1. I follow the tutorial in https://www.cybrosys.com/blog/how-to-setup-sftp-server-on-ubuntu-20-04

and I can successfully login sftp, but after login, the default folder is "/", and can't create folder in "/". What I want is when the user login sftp, the default folder is the user home directory, like "/home/sftp_user" and can create folder under "/home/sftp_user"

the /etc/ssh/sshd_config is as follow:

Subsystem       sftp    internal-sftp

Match group sftp
ChrootDirectory /home
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp

access right under /home directory is as follow:

drwxr-xr-x  4 root      root 4096 Nov 19 17:59 .
drwxr-xr-x 20 root      root 4096 Oct 30  2023 ..
drwxr-x--- 35 abc       abc  4096 Nov 20 18:28 abc
drwxrwxrwx  8 sftp_user sftp 4096 Nov 20 18:32 sftp_user

If I change ChrootDirectory /home to %h, then when login sftp [email protected]

it return "client_loop: send disconnect: Broken pipe". I google and said the ChrootDirectory must owned by root and not writable by others, But then if it is not writable by others, then how can I create a directory under ChrootDirectory?

  1. in tutorial https://www.cybrosys.com/blog/how-to-setup-sftp-server-on-ubuntu-20-04,
    the subsystem is

    Subsystem sftp /usr/lib/openssh/sftp-server

but I see many other tutorial, the subsystem is

Subsystem       sftp    internal-sftp

what should I use?

2 Answers 2

0

The reason for the behavior you're seeing is a long-standing bug/misfeature of the OpenSSH ChrootDirectory support. However, it has an easy workaround.

When you specify a ChrootDirectory for a user (or a group of users), the SSH/SFTP sessions the setting is applied to will see the directory specified by the ChrootDirectory directive as the root directory (/). This makes any files that are not in the ChrootDirectory or its subdirectories inaccessible to those sessions: there will be no way to construct a pathname that would refer to such files.

The bug/misfeature is, when OpenSSH is applying the ChrootDirectory directive, it will not make a corresponding change to the user home directory path it read from /etc/passwd. As a result, if ChrootDirectory /home is in effect for a user with home directory /home/sftp_user, then sshd will be trying to find /home/home/sftp_user which obviously doesn't exist.

The workaround for this is to create a symbolic link at /home/home pointing right back to the current directory:

cd /home
sudo ln -s . home  #yes, exactly like this

After this, the home directory path /home/sftp_user will be applicable both inside and outside the chroot, and the chrooted sftp_user will see a writeable home directory as /home/sftp_user -> /./sftp_user == /sftp_user.


The tutorial you're using has the SFTP subsystem configuration line as

Subsystem      sftp    /usr/lib/openssh/sftp-server

This does not work when ChrootDirectory /home is in effect, as /usr is not under /home and thus will be inaccessible.

The tutorial works around this by using ForceCommand internal-sftp.

For now, both ways seem to work, but a future update to OpenSSH might make the subsystem logins more strict, and cause the login to fail if the specified subsystem is not actually available, before the ForceCommand takes effect. I would consider the Subsystem sftp internal-sftp to be slightly more robust and future-proof.

3
  • because sshd cannot found /home/home/sftp_user, so after login, it default to the "/"? Commented Nov 21, 2024 at 7:47
  • I change ChrootDirectory from /home to /, then it also works without creating symbolic link, thanks for your solution. Commented Nov 21, 2024 at 7:52
  • 2
    If you use ChrootDirectory /, it's the same as not using ChrootDirectory at all. The ChrootDirectory directive is not necessary for the SFTP server function: it is only needed if you want to restrict the SFTP users to seeing only a strictly limited part of the system. Commented Nov 21, 2024 at 7:58
0

The info you Googled for chroot was for the command rather than the configuration setting in the sshd_config file. It doesn't apply to the SFTP settings you're trying to use.

The sshd_config file parameter ChrootDirectory %h is correct.

  • The user must exist in the authentication system (for you that's probably local authentication using the /etc/passwd and /etc/shadow files).
  • The user's home directory field in the /etc/passwd entry should not be empty, and that home directory must have been created on the filesystem. The home directory itself should be owned by the user and the user's primary group (the uid and gid in the /etc/passwd entry), with permissions 0711 or 0755. My own preference is 0711.
  • The parent directories above the SFTP user's home directory are usually owned by root, gid root, with permissions 0755.
  • The .ssh directory under the user's home directory has the same owner/group as the home directory, with permissions 0700. Files in the .ssh directory should have 0600 permissions. Some files can have the slightly more open 0644 or 0640 permissions, but other files must not readable by anyone but the owner. For me, using 0600 permissions for all the files works, and is easier to remember.

With these settings, your SFTP user will not be able to chdir outside the home directory, but can read and write files under the home directory. (can create and delete subdirectories under the home directory, too). This means the user can overwrite or delete/create their own authorized_keys file in the default location (~/.ssh/authorized_keys).

My tests show that the SFTP user can even delete their own home directory. If they do, they are stuck - they can't create their home directory again (no write permissions in the parent dir), and their next login attempt will fail because of the missing home directory.

If you don't want the user to manipulate their authorized_keys file, you can use the AuthorizedKeysFile /path/to/authorizedkeys/%u parameter to put the file somewhere outside the user's home directory, where they can't touch it. If you do, the file itself must be owned by the SFTP user and their primary group, with 0600 permissions, and must be in a directory with 0711 or 0755 permissions (0711 preferred), but this directory can be owned by root, group root. Parent directories of that directory should be owned by root, group root with 0755 permissions.

The path in the example above, /path/to/authorizedkeys/%u is just an example. The %u for the filename means it's the same as the username, which helps keep the keys organized for multiple SFTP users.

There's some additional config steps if you want to have some users who can only do SFTP and other users who can do interactive logins (like system admins). I haven't included those steps in this answer, but I can if you want.

3
  • The sshd of modern OpenSSH enforces the restriction that the ChrootDirectory must be writeable by root only; if this is not true, the login will fail. If a chroot directory is writeable by the chrooted user, there are some known methods to escape from a chroot; the OpenSSH requirement to have a read-only ChrootDirectory is to block these escape methods. Commented Nov 21, 2024 at 6:20
  • @telcoM The config I described has been working for me on an Ubuntu 22.04 machine for the past 2-3 years. dpkg-query -W shows the package version string as 1:8.2p1-4ubuntu0.11. Is the "modern" OpenSSH you mention newer than that? Commented Nov 21, 2024 at 6:53
  • The chrooted SFTP servers I've set up have been RHEL/CentOS for the most part, using whatever was the current supplied OpenSSH in RHEL 7, 8 and 9. I guess Ubuntu may have applied their own patch to solve the chroot escape problem in a different way. If that's not the case, they may have a security regression. Commented Nov 21, 2024 at 8:04

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.