20 October 2017

Secure FTP on S3 with Chroot and Google Authenticator

Secure FTP is really SSH under the covers behaving like an FTP (file transport) service. And instructions exist leveraging S3 as an inexpensive file system backend. But getting SFTP and S3 deployed securely with users isolated took some detective work. Isn't it a odd that secure instructions always take work? Cobbled from multiple sources, here are flexible instructions to get an up to date, robust, secure installation going.

As I've been working a lot in AWS Gov Cloud, these instructions account for this wrinkle.

Multi-factor (MFA) client access is included, since this is quickly becoming a standard requirement.

These instructions assume the following;

Ubuntu 16.04 LTS with SSH- a mature Ubuntu version with long term support

Optionally enable MFA capability for SSHNote: It is always a good idea when making SSH changes to leave a separate console open and then test the change. Otherwise it is easy to lose access to the box if a mistake is made.

sudo vim /etc/ssh/sshd_configChallengeResponseAuthentication yes

For now, protect the ubuntu user access by adding these lines to the sshd_config. It can be updated later once everything is complete.

The nullock flags allows for a user who does not have Google Authenticator set up to be able to log in.

Create and Prepare the Mount Point for the S3 bucket

On AWS S3, create a non-public bucket with an account that has API keys - API keys are created in the IAM section of AWS. Using the AWS GUI to create a bucket with owner ACLs (the default) will work just fine.Create a password file for the S3 file system.

sudo vim /etc/passwd-s3fs

The file format is as follows: bucketname:accessKeyID:secretKeyID

And then lock it down.

sudo chmod 640 /etc/passwd-s3fs

Create a mount point that is owned by root.

sudo mkdir -p /s3/home

A side bar about mounting a Chroot DirectoryIn the world of SFTP, using a ChrootDirectory is
necessary to limit file system access to users. Without it, SFTP users will be able to
traverse all over the server file system and download anything a
regular user has read access to, including the passwd file.Mounting the bucket takes a bit of explanation and is very the much the secret sauce to getting this to work correctly. Most online instructions suggest a simple mount command as the root user or mounting with the allow_other flag to allow others to use the mount point.

Both of these options will fail when using a ChrootDirectory. A look at the man pages explains why:

ChrootDirectorySpecifies the pathname of a directory to chroot(2) to after
authentication. At session startup sshd(8) checks that all com-
ponents 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.

When mounting the bucket as the root user, the mount point permissions will be 700. This means only the root user will have access to what is below. Chroot will fail for SFTP users with a permission denied error:

safely_chroot: stat("/s3/home/"): Permission denied

When mounting the bucket with the allow_other flag, the mount point permissions will be 777. This means the mount point is too permissive. Chroot will fail for SFTP users with a bad ownership error:

Creating New Groups for SFTP Users

Users who need to access the same files should be put into groups. The groups can then be locked down to specific directories on the bucket. Generally, this should be scripted out. But here are the basic steps to get started.

# Add the full path to the groupsudo chgrp -R (groupName) /s3/home/(groupName)/

Then add that detail to sshd_config so any new SFTP user in that group is locked down to only using SFTP.

BUCKET_HOME="(mountPoint)"GROUPNAME="(groupName)" cat <<EOT>> /etc/ssh/sshd_config # Lock down the new group Match Group ${GROUPNAME} # Only allow SFTP and chroot to the required directory. ForceCommand internal-sftp ChrootDirectory ${BUCKET_HOME}/${GROUPNAME}/ # Lock down SSH options PermitTunnel no AllowAgentForwarding no AllowTcpForwarding no X11Forwarding no EOT

And don't forget to restart SSH to catch the change.

systemctl restart sshd.service

Add New Users

Adding new users is straightforward now that everything has been set up.

sudo adduser --ingroup (groupName) (newUser)passwd (newUser)

Optionally set the MFA

sudo su - (newUser) google-authenticator

And note the key for the user.

A successful test should do the following:

Allow the user to log into the system via SFTP

The user should be directed on the chroot environment and only see the "controlled" folder