Using sftp-server to replace FTP

In my job, data collection and data deliveries are either done via API or FTP. FTP has it’s drawbacks, but ultimately gets the job done. Some of those issues are more specific to the lack of improvements in the technology, efficiency of the protocol, scaling, availability, file-locking and active vs. passive  connections vs. the Firewall security -and so on. Not all are impossible challenges, but unnecessary in today’s cloud orientated technology world.

We still can’t get rid of the ability to transfer exported data and deliver over a file transfer protocol, however, we can change the protocol and the data handler and create a secure method that’s much easier to deal with.  While it’s possible to run FTP and SSL/TLS for security, SFTP provides a much less intrusive replacement.

In a past post, I offered a method which allowed users to create a secondary service that was dedicated to SFTP and not use SSH to connect to a console. later versions of openssh don’t support the same method due to shared memory overlap, but – if you really want to create an isolated and dedicated SFTP service, then consider docker instead. In this guide, I’m going to show how to secure your existing SSH for both remote console and SFTP-only.

Step one: SFTP vs SSH (Shell)

I’m going to refer to SSH as “shell access” and SFTP as just “sftp without shell access”.  I also use debian, so you’ll just a have to adapt for your own distro.

My /etc/ssh/sshd_config looks like this:

Listen 7387
Listen 22


# applies to members of the 'sftponly' group and are 
# coming in on port 7387
Match Group sftponly LocalPort 7387
      ChrootDirectory %h
      X11Forwarding no
      AllowTcpForwarding no
      ForceCommand internal-sftp -u 000

External firewall port-forwards port 7387 only.
I leave it up to you if you want to use password or keys.

Step two: add sftp as a shell

echo "/usr/lib/openssh/sftp-server" >> /etc/shells

Step three: Create the group and first user

Create the sftponly group; I like mine to be system accounts, but it does not have to be.
groupadd --system sftponly

Create the user:
~# useradd --shell /usr/lib/openssh/sftp-server --user-group --home-dir /path/to/sftproot/userdir --groups sftponly

Annoyingly, the sftp server chrootdir directive requires the sftp-root is owned by root.
~# chown root:root /path/to/sftproot/userdir

Extending Security

I recommend that users still use firewall ACL’s to limit who can access their SFTP server in the first place, but if you provide a service to anyone-anywhere, then consider basic isolation practices and enhance the security further.

  1. Isolate the host serving sftp service
  2. Run read-only and restricted r/w capability (docker is good for this)
  3. Disable password authentication, use RSA certificates with a password in it.
  4. If you need to use passwords make sure you enforce complex and long passwords! Here’s a neat one-liner for password generationopenssl rand -base64 15
  5. Can you also support a two-factor method? Google-auth is pretty easy to integrate with and there are more options available if you look around. A nice cheap two-factor is to use both an rsa pubkey with a password and the user password.
    AuthenticationMethods "publickey,password publickey,keyboard-interactive"