Restrict SFTP User Access to Specific Directories in Linux

|
Last Updated:
|
|
Restrict SFTP User Access to Specific Directories in Linux

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.

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).

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

Connect to WiFi in Linux Using NMCLI command

SUPPORT US VIA A VIRTUAL CUP OF COFFEE

We're passionate about sharing our knowledge and experiences with you through our blog. If you appreciate our efforts, consider buying us a virtual coffee. Your support keeps us motivated and enables us to continually improve, ensuring that we can provide you with the best content possible. Thank you for being a coffee-fueled champion of our work!

Photo of author
koromicha
I am the Co-founder of Kifarunix.com, Linux and the whole FOSS enthusiast, Linux System Admin and a Blue Teamer who loves to share technological tips and hacks with others as a way of sharing knowledge as: "In vain have you acquired knowledge if you have not imparted it to others".

1 thought on “Restrict SFTP User Access to Specific Directories in Linux”

  1. 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?

    Reply

Leave a Comment