Baeldung Pro – Linux – NPI EA (cat = Baeldung on Linux)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

1. Overview

SFTP (Secure File Transfer Protocol) is a popular method for transferring files securely over a network. It uses SSH (Secure Shell) to encrypt communications.

In this tutorial, we’ll see the process of configuring a Linux server to permit SFTP connections while disallowing SSH connections.

2. Introduction

Secure File Transfer Protocol (SFTP) is a secure method for network file transfer. It’s built on the top of SSH and provides a similar level of security. However, unlike SSH, SFTP doesn’t provide full shell access. Consequently, this makes it a more secure option for scenarios where only file transfers are necessary.

In other words, such a configuration is beneficial when we want secure file transfer without compromising the security of a system by allowing full shell access. In these cases, administrators can allow users to upload and download files but prevent them from running commands on the server.

3. Use Cases for SFTP Instead of Pure SSH

Several situations may require limiting SSH access while allowing SFTP:

  • Hosting Services: clients may upload files but shouldn’t have shell access
  • Data Transfers: sharing files with external clients in a secure and controlled way
  • Backup Services: file backup and restore data to and from remote servers without SSH login

Thus, restricting SSH access enhances security. It minimizes potential attack surfaces while still allowing file transfers to occur securely.

4. Using Restricted SSH Access

Effectively, we can allow SFTP but disallow SSH access by configuring the SSH daemon to use the SFTP server. In addition, this involves setting up a limited user environment, restricting their access to only SFTP.

Let’s see how to configure restricted SSH access.

4.1. Configuring a New Group for SFTP Users

First, we create a dedicated group for SFTP users:

$ sudo groupadd sftpusers

The users in the new group have only file transfer access to the server. For this, we later modify the sshd_config file. Of course, we can either assign existing users or add new users to this group.

In this case, let’s add a new user, baeldung, to the above group:

$ sudo useradd -m -d /home/baeldung -g sftpusers baeldung

Notably, the options -m and -d set the home directory for the user as /home/baeldung.

Next, we add a password for the new user:

$ sudo passwd baeldung

Alternatively, we can also add an existing user to the sftpusers group.

4.2. Creating a Shared Directory

A chroot environment confines users to a part of the system, isolating them from the rest.

To begin with, let’s create a new directory for the SFTP users to control their access:

$ sudo mkdir /home/baeldung/uploads

The new directory, uploads, belongs to the currently logged-in user. So, we now assign ownership of the chroot directory and its parent directories to the root:

$ sudo chown root:root /home/baeldung/
$ sudo chown root:root /home/baeldung/uploads/

The above ownership rights match the OpenSSH server directive for ChrootDirectory configuration.

Next, we set access permissions for the files inside the uploads directory. In general, root has full access, while others have only read and execute access:

$ sudo chmod 755 /home/baeldung/uploads/

As a result, baeldung can only upload files to the uploads directory.

4.3. Modifying the sshd_config File

Next, we modify the sshd_config configuration file. In this file, we use the internal-sftp parameter set against the Subsystem directive:

$ cat /etc/ssh/sshd_config
...
Subsystem sftp internal-sftp
...

Thus, the above setup enables SFTP with the internal-sftp server. Alternatively, we can use the sftp-server binary for implementing the subsystem.

Furthermore, at the end of the file, we specify a group of users with restricted SFTP access:

$ cat /etc/ssh/sshd_config
...
Match Group sftpusers
    ChrootDirectory /home/baeldung/uploads
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no
...

Let’s see a breakdown of the above parameters:

  • Match Group: the user group to restrict
  • ChrootDirectory: confines the users to their home directory
  • ForceCommand internal-sftp: forces users to use the internal SFTP server
  • AllowTcpForwarding and X11Forwarding: disable port forwarding and X11 forwarding

After saving the configuration file, we restart the SSH service to apply the changes:

$ sudo systemctl restart sshd

Finally, we can test our setup.

4.4. Logging on to the SFTP Server

Let’s open a terminal on the client and try to access the uploads directory on the server:

$ sftp [email protected]
...
[email protected]'s password: 
Connected to 192.168.29.22.
sftp>

As a result, we can log in as baeldung.

Additionally, we can check the chroot environment on the remote machine. To do this, we list the current working directory:

sftp> pwd
Remote working directory: /

Then, we move a level up in the directory and again see the current directory:

sftp> cd ..
sftp> pwd
Remote working directory: /

Similarly, we try logging in via ssh:

$ ssh [email protected]
[email protected]'s password: 
This service allows sftp connections only.
Connection to 192.168.29.22 closed.

Thus, the setup seems to be working properly and doesn’t allow SSH access.

5. Using /bin/false or /bin/nologin for Shell

Another method to disallow SSH access while enabling SFTP is to assign users a non-functional shell.

There are two popular binaries for this purpose:

  • /bin/nologin
  • /bin/false

While both function the same way for our purposes, we use /bin/false for this demonstration.

5.1. Setting Up the User

First, we add a new user, baeldung1, in the sftpusers group:

$ sudo useradd -m -G sftpusers baeldung1

Next, we set a password for the new user:

$ sudo passwd baeldung1

Of course, we assign the /bin/false shell:

$ sudo usermod -s /bin/false baeldung1

Again, we create a directory for a chroot environment:

$ sudo mkdir /home/baeldung1/uploads

Next, we change the directory permissions:

$ sudo chown root:root /home/baeldung1/

Similarly, we set the ownership for the uploads directory:

$ sudo chown root:root /home/baeldung1/uploads/

Finally, we set the permissions for root and others:

$ sudo chmod 755 /home/baeldung1/uploads/

As a result, the root has all the accesses and others have only read and execute accesses.

5.2. Testing

To verify the setup, let’s try to log in from another machine:

$ sftp [email protected]
[email protected]'s password:
Connected to 192.168.29.22.
sftp>

Further, we check the current directory on the remote server:

sftp> pwd
Remote working directory: /

Also, we can try navigating outside of the chrooted directory:

sftp> cd ..
sftp> pwd
Remote working directory: /

As a result, we see we can’t leave the chroot environment.

Let’s also try to log in via ssh:

$ ssh [email protected]
[email protected]'s password: 
This service allows sftp connections only.
Connection to 192.168.29.22 closed.

As a result, ssh connection isn’t allowed.

In the same way, we can use the /bin/nologin shell.

6. Using scponly

Another useful method to restrict SSH access is by using the scponly utility. This utility restricts users to file transfer operations without allowing SSH shell access.

6.1. Installation

scponly is currently available on GitHub. Moreover, it has not been updated for a long time. Thus, some features such as the chroot setup might not work.

Let’s install scponly from the source code.

First, we update the package list on the system:

$ sudo apt update

Next, we install the essential tools for building software from source code. This includes the GNU Compiler Collection (GCC), make, and other tools:

$ sudo apt install build-essential

Since /opt is a common location for manually installed software, let’s move there:

$ cd /opt

Next, we download the scponly source code using the wget command:

$ sudo wget http://sourceforge.net/projects/scponly/files/scponly-snapshots/scponly-20110526.tgz

Next, we extract the downloaded .tbz file:

$ sudo tar -zxvf scponly-20110526.tgz

Moving on, we navigate to the extracted directory:

$ cd /opt/scponly-20110526

Now, we run the configuration script, specifying the path to the sftp-server binary:

$ sudo ./configure --with-sftp-server=/usr/lib/openssh/sftp-server

The above script checks for all the required dependencies for the build and install process.

Further, we use the make command to compile the source code:

$ sudo make

To install the compiled scponly binary, we leverage the install subcommand:

$ sudo make install

As a result, the files are installed in their proper directories.

6.2. Adding the scponly Shell

Next, we add the scponly shell to the system’s list of valid shells (/etc/shells):

$ sudo sh -c "echo "/usr/local/bin/scponly" >> /etc/shells"

As a result, users should now be able to use the scponly shell.

6.3. Creating a scponly User

Finally, to test the setup, we create a user, scponly:

$ sudo useradd -d /home/scponly -s /usr/local/bin/scponly scponly

The above user has a home directory of /home/scponly. Also, the shell is set as /usr/local/bin/scponly, which restricts the user to file transfers only.

Naturally, we set a password for the user:

$ sudo passwd scponly

Let’s test the result.

6.4. Testing

To test the user with scponly, we try to log in from another machine with that user:

$ sftp [email protected]
[email protected]'s password: 
Connected to 192.168.29.22.
sftp>

Thus, we’ve successfully connected to the remote machine over SFTP.

Let’s again try by logging in via ssh:

$  ssh [email protected]
[email protected]'s password: 
Welcome to Ubuntu
...
Could not chdir to home directory /home/scponly: No such file or directory
Connection to 192.168.29.22 closed.

Thus, the connection is automatically closed.

7. Conclusion

In this article, we’ve seen how we can allow SFTP connections while denying SSH login. We employed several methods for this purpose:

  • restricted SSH Access
  • non-functional shells like /bin/false
  • scponly utility

Effectively, the above approaches provide a secure and controlled way to transfer files without compromising our system security.