Forward SFTP user to chroot subdirectory after authentication

I've set up a SFTP server using OpenSSH, everything works fine and the users I created can connect.

After authentication, the users find themselves directly inside /chroot, a directory they are not allowed to write into. So I've put a /subdirectory into /chroot they have write access to (inspired by this blog post) which works fine as well.

However, due to the nature of the project I'm working on, users should find themselves directly in a folder they are allowed to write into after authentication. Forwarding them into the /chroot/subdirectory might be the best solution but I've found no resource explaining how to achieve that.

Can it be done? How?


Solution 1:

[EDIT] Yes I believe it is possible, but I also believe not with openssh:

Here is how I chroot sftp using openssh:

I put sftp users in a special group sftponly which is identified in the sshd_config file. I make sure sftp users have no shell (so they can't log in with ssh) and use the .%h environment variable to force them into a sftp chroot subdir named after their home directory using the ChrootDirectory directive. Other environment variables interpreted by sshd_config are documented in the sshd_conf man page like so:

The pathname may contain the following tokens that are expanded at runtime once the connecting user has been authenticated: %% is replaced by a literal '%', %h is replaced by the home directory of the user being authenticated, and %u is replaced by the username of that user.

Here is a copy of my notes for achieving this on OpenBSD, if you use a different system the .%h environment variable may of course differ:

# 1. Create the sftp jail directories
# These directory permissions work with this /etc/ssh/sshd_config:
# drwxr-xr-x  4 root    wheel  512 May 14 16:20 /home/sftproot
# drwxr-xr-x  3 root  wheel  512 May 14 16:21 /home/sftproot/home
# drwxr-xr-x  3 root  wheel  512 May 14 16:37 /home/sftproot/home/User01
# drwxr-xr-x  3 User01  sftponly  512 May 14 16:39 /home/sftproot/home/User01/upload
# drwxr-xr-x  3 root  wheel  512 May 14 16:37 /home/sftproot/home/User02
# drwxr-xr-x  3 User02  sftponly  512 May 14 16:39 /home/sftproot/home/User02/upload

# 2. Make sure /etc/ssh/sshd_config jails /home/sftproot/.%h

# 3. Create a group whose members will only be allowed sftp access
# groupadd sftponly

# 4. Create User01 + User02 whom will only get sftp access
# useradd -s /sbin/nologin -m -G sftponly User01
# useradd -s /sbin/nologin -m -G sftponly User02

# 5. In /etc/ssh/sshd_config enable use of chroot(internal-sftp) then force chroot dirs per user:
# override default of no subsystems
# Subsystem     sftp    /usr/libexec/sftp-server
# Subsystem       sftp    internal-sftp
# Rules for sftponly members
# Match group sftponly
#         ChrootDirectory /home/sftproot/.%h
#         X11Forwarding no
#         AllowTcpForwarding no
#        ForceCommand internal-sftp

# [Comment] Make sure /etc/ssh/sshd_config jails /home/sftproot/.%h
# Which will translate .%h to /home/$username

# [Comment] The sftp users will not be able to log in outside of sftp (as they have no shell).
# As they sftp in they will land in the /home/sftproot/home/Userxx directory which
# will be named "./" and where they have no write access.
# However the directory ./upload is read/writable.

[EDIT part 2] However, the sshd_conf man page also specifies that:

ChrootDirectory

Specifies the pathname of a directory to chroot(2) to after authentication. At session startup sshd(8) checks that all components of the pathname are root-owned directories which are not writable by any other user or group. After the chroot, sshd(8) changes the working directory to the user's home directory.

So the chroot directory path, including the part specified by variable expansion, is expected and tested for by sshd to be owned and writable exclusively by root. Therefore, a user of an openssh sftp chrooted service needs writable subdirectories to be able to write to the home directory.

I believe this is not a requirement with all ssh servers however. We also use Tectia where I observe that users are able to write to their respective root directories. However we run it only where Windows is a requirement, so regrettably I cannot readily test the corresponding *nix configuration. The Tectia sftp chrooting support page does not explicitly specify that the user home needs to be owned by root in a Unix environment. I would therefore guess that with Tectia this is not a requirement but that the ownership of a chrooted user home rootdir may be that of the actual user.

Solution 2:

ChrootDirectory /upload/%u

ForceCommand internal-sftp -d data

This will put the sftp in /upload/UserXX/data directory. The data directory is owned and read/writable by the UserXX