In this guide, we are going to learn how to restrict SFTP user access to specific directories in Linux systems. SFTP, an acronym for Secure File Transfer Protocol is a secure file transfer protocol that runs over SSH. It offers all the features offered by the legacy FTP protocol but in a more secure manner.
Table of Contents
Restrict SFTP User Access to Specific Directories in Linux
In order to restrict SFTP user access to specific directories in Linux, SFTP chroot jails are used. The SFTP chroot jail ensures that an SFTP user, onced login to a system, is confined only to specific directories with no access to other directories on the system.
OpenSSH comes with the support for SFTP chroot jails by default.
Install OpenSSH Server
In order to be able to configure restricted directory access for SFTP users, ensure that OpenSSH server is installed.
OpenSSH Server can be installed by running the command belows;
On CentOS and Other RHEL derivatives;
yum -y install openssh-server openssh-clients
On Ubuntu and Other Debian derivatives;
apt install openssh-server -y
For other Linux distros, consult your distro guide on how to install OpenSSH server.
Create Unprivileged SFTP User Account
Create a group to assign SFTP user accounts to. Note that this is not necessary as the directories you will be assigning the user may already have specific group assigned to them.
groupadd sftpgroup
Next, create a less privileged account for an SFTP user. Replace the username accordingly;
useradd -M -g sftpgroup -s /usr/sbin/nologin sftpuser
If for example you are restricting SFTP user access to web server directories like Nginx and Apache root directories, that are already owned by the group nginx
, apache
or www-data
, you would simply set the primary group of the user by replacing the sftpgroup
with either nginx
, apache
or www-data
.
useradd -M -g nginx -s /usr/sbin/nologin sftpuser
useradd -M -g apache -s /usr/sbin/nologin sftpuser
useradd -M -g www-data -s /usr/sbin/nologin sftpuser
You can as well be able to change the user’s primary group using the usermod
command. For example, to change the default group of an sftpuser
to apache
, simply run;
usermod -g apache sftpuser
Note that the group must exist for the command above to succeed.
You can also add sftpuser to an existing group (Secondary group).
usermod -aG apache sftpuser
Create a password for the user to unlock its account.
passwd sftpuser
Verify the groups the user belong to;
groups sftpuser
sftpuser : www-data
Restrict SFTP User Access to Directory with Chroot Jail
Once you have an SFTP user with primary group set to be similar with the group of the directory you are limiting access to, you can configure the Chroot jain using OpenSSH.
OpenSSH enables you to specify pathname of a directory to which the user will be confined to after authentication through the use of the ChrootDirectory
parameter.
Open the SSH configuration file for editing;
vim /etc/ssh/sshd_config
Enable SSH in-process SFTP server by commenting (add # at the beginning) the following line…
# override default of no subsystems
Subsystem sftp /usr/libexec/openssh/sftp-server
… and replacing it as follows;
Subsystem sftp internal-sftp
Next, add the following configuration options after the line above;
Match User sftpuser
ChrootDirectory /var/www/html/
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
Such that you configuration looks like;
...
# override default of no subsystems
#Subsystem sftp /usr/libexec/openssh/sftp-server
Subsystem sftp internal-sftp
Match User sftpuser
ChrootDirectory /var/www/html/
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
...
Note the directory name assigned to ChrootDirectory
. This specifies the directory to which the user, specified by the Match User
option has access. In this case, the directory is /var/www/html/kifarunix
.
ls -alhd /var/www/html/kifarunix/
drwxr-xr-x 5 www-data www-data 4.0K Mar 16 14:59 /var/www/html/kifarunix/
Also pay attention here:
man sshd_config
:
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.
The bind path, in this case, /var/www/html
, therefore needs to be fully owned by root
to ensure that the SFTP user has no access beyond its chroot jail.
ls -alh /var/www/html
total 4.0K
drwxr-xr-x. 4 root root 34 Mar 16 21:56 .
drwxr-xr-x. 4 root root 33 Mar 12 15:20 ..
drwxr-xr-x. 5 apache apache 4.0K Mar 16 21:56 kifarunix
For more explanation on options used, simply consult, man sshd_config
.
If you need to specify a specific group, simply replace the line, Match User sftpuser
with Match Group sftpgroup
replacing the names of the group accordingly.
How to Restrict SFTP User to read-only Access
You can restrict sftp user to read-only access by updating the line below from;
ForceCommand internal-sftp
To;
ForceCommand internal-sftp -R
This option restricts the client to read-only access within the chrooted environment.
Restart SSH service
Check SSH configurations for any errors;
sshd -t
If the configuration file contains no syntax errors, the command will produce no output and return to the command prompt. If there are any syntax errors, it will print an error message indicating the location and nature of the error.
If no error;
systemctl restart sshd
or
systemctl restart ssh
Verifying SFTP User Restricted Directory Access
Note that, in our setup above, we have restricted access for the SFTP user, sftpuser
to the web server root directory, /var/www/html/kifarunix
.
To verify the access controls, login as SFTP user. Relace the username and server_IP accordingly;
sftp sftpuser@server_IP
If SSH is running on non default port, you need to specify the port;
sftp -P port sftpuser@server_IP
Once you login, check the current working directory;
sftp> pwd Remote working directory: / sftp>
List the contents
sftp> ls kifarunix sftp>
Notice the sub-directory under the ChrootDirectory.
sftp> cd ../../
sftp> pwd
Remote working directory: /
sftp> ls
kifarunix
sftp>
As you can see from the output of the command above, the sftpuser has no access outside the specified directory and that is how simple it is to restrict access of an SFTP user to a specific directory.
That marks the end of our on how to restrict SFTP User Access to Specific Directories in Linux.
You can also read about SFTP chroot on HowTo: chroot SFTP (only).
Related Tutorials
Run only Specific Commands with sudo in Linux
How to Add Users to sudo group in Linux
Using Find Command to Search for Files and Directories in Linux
Great tutorial, but I see that all sftp tutorials miss one critical point. The sftp user must not have access to ChrootDirectory! I have multiple websites, and I want a sftp user per website and each user must not be able to see the other websites and download their files! For example I have the following structure:
/var/www/website-one/
/var/www/website-two/
/var/www/website-three/
If I set ChrootDirectory to /var/www/ all the sftp users will see the other folders and be able to download them. They will not be able to upload files to the other folders. How the hell do I make them STAY in their own directories, without being able to view the others, and also make SFTP work? If I change the ChrootDirectory to /var/www/website-one/, SFTP will stop working, because ChrootDirectory needs to only have root permissions.
On my shared hosting that has cPanel, all FTP users have access only to their own directory and can’t see anything else. I want to achieve the same, without having to have a subfolder to serve the website from. Meaning no /var/www/website-one/public_html/index.html but /var/www/website-one/index.html Is this even possible with OpenSSH?