Bind mount an SFTP user after using chroot
Last updated on: 2019-02-08
Authored by: Rackspace Community
This article is intended for administrators or developers.
Bind mounting a Secure File Transfer Protocol (SFTP) user on which the chroot operation has been performed on your Red Hat® Enterprise Linux® (RHEL®) and CentOS® 6 (OpenSSH is 4.9p1 or later) servers creates the following conditions:
- The user can only use SFTP and does not have full shell access over Secure Shell (SSH).
- The user is jailed to their home directory and has no way of breaking out of it.
- From the user’s perspective, their home directory is on the server.
- This bind mounting is often needed for a developer that might need write access to one (or more) Apache® document root or roots or some other directory for the purpose of uploading or editing web content.
This article describes how to use the chroot operation to set the home directory for the user
and create a bind mount within that home directory for any of the external (document root) directories
to which they need access. A bind mount is the only way to give the user access to data outside of
their chroot directory. You are not able to use a symbolic link (symlink) to data outside of the chroot
directory into it (for example,
ln -s /home/user/http /var/www/http). After the chroot operation,
the file system has no knowledge of any data outside of the chroot directory. This lack of knowledge breaks the symlink.
As an alternative, you can move the document root directory to the user’s home directory,
and then symlink it to the original location (for example,
ln -s /var/www/html /home/user1/html).
The SSH daemon (SSHD) offers some dynamic variables in the configuration for the chroot operation:
%u: username of the user logging in
%h: $HOME of the user logging in
SSHD is very strict about how you must set permissions. One of these restrictions is that the user cannot write to the top level of the chroot directory. You must choose an appropriate top level for the chroot directory, such as the following settings:
- Set ChrootDirectory to
%h: The user cannot write to their home path. They need either a subfolder they can write to (for example uploads), or a bind mount to another location they can write to (for example
- Set ChrootDirectory to
/home/chroot: The user can write to their home path, but the top level of the chroot directory is protected with file system permissions, not the chroot jail.
The first option uses the chroot directory to guarantee security instead of relying on file system permissions. The second option allows writing to the home directory but means the chroot directory is shared with other users, and only file system permissions stop information disclosure. The right option depends on your needs.
Bind mount an SFTP user after a chrooted operation
Use the following steps to bind mount the user:
Create a group to which you will assign any user that needs to be jailed to their home directory:
# groupadd sftponly
Create the user. Set the shell to
/bin/falseand assign the user to the group that you created above:
# mkdir -p /home/chroot/$NEWUSER # useradd -d /$NEWUSER -s /bin/false -G sftponly $NEWUSER # Note: homedir is relative to the chroot # pass}wd $NEWUSER
Comment out the following line:
Subsystem sftp /usr/libexec/openssh/sftp-server
Add the following lines to the end of the file:
Subsystem sftp internal-sftp Match Group sftponly ChrootDirectory /home/chroot # OR ChrootDirectory %h X11Forwarding no AllowTCPForwarding no ForceCommand internal-sftp
Test the configuration, and then reload the SSHD:
# sshd -t # service sshd reload
Set up the user’s homedir afer the chroot operation
If the ChrootDirectory is
/home/chroot, run the following commands:
# chmod 711 /home/chroot # This prevents chrooted users from seeing other chrooted users' homedirs # chmod 755 /home/chroot/$NEWUSER # chown $NEWUSER:sftponly /home/chroot/$NEWUSER
If the ChrootDirectory is
%h, run the following command:
# chown root:root /home/chroot/$NEWUSER
Create bind mounts to any path outside the chroot directory that the user needs to access
Add the following line to the
/var/www/html /home/chroot/$NEWUSER/www none bind 0 0`
Mount the directory:
# mkdir /home/chroot/$NEWUSER/www # mount /home/chroot/$NEWUSER/www
Update the file system permissions on the directories the user accesses. Take into consideration other users that currently have read/write access to make sure you do not inadvertently remove their permissions. You can complete this step in in several different ways, such as changing user ownership, changing group ownership or permissions, or adding file access control lists (FACLs).
The following example shows commands for adding FACLs:
# setfacl -Rm u:$NEWUSER:rwX /home/chroot/$NEWUSER/www/ # setfacl -Rm d:u:$NEWUSER:rwX /home/chroot/$NEWUSER/www/
The following problems can occur.
Directory permissions can cause the following problems:
The built-in chroot function of SFTP is very strict about permissions. If the permissions are not secure enough, you receive the following error when you try to log in:
root@ftp01[ ~ ]# sftp $NEWUSER@localhost Connecting to localhost... chroottest@localhost's password: Write failed: Broken pipe Couldn't read packet: Connection reset by peer
You might be able to log in, but you cannot upload files. In this case you receive the following error:
sftp> put test Uploading test to /$NEWUSER/test Couldn't get handle: Permission denied In both cases the problem is directory permissions. Here's what a known-good directory structure looks like: root@ftp01[ ~ ]# ls -ld / /home /home/chroot /home/chroot/$NEWUSERdrwxr-xr-x. 28 root root 4096 Aug 22 10:31 / drwxr-xr-x. 18 root root 4096 Oct 10 10:49 /home drwx--x--x 3 root root 4096 Oct 10 10:49 /home/chroot drwxr-xr-x 3 $NEWUSER $NEWUSER 4096 Oct 10 11:40 /home/chroot/$NEWUSER root@ftp01[ ~ ]#
SCP does not work
This type of user only works with SFTP and does not work with other protocols (for example, remote shell (RSH), secure contain protect (SCP), or File Transfer Protocol (FTP)).