sftp gives permission denied only when chrooted?

I found the solution on this page. To summarize, after configuring sftp as per the above configuration, the following two commands needed to be run to allow access with SELinux enabled:

setsebool -P ssh_chroot_rw_homedirs on
restorecon -R /home/$USERNAME

In this case, the second command would be restorecon -R /home/pilots. After this, sftp works as expected, even when chrooted, without having to disable SELinux completely.


Tailing off of @ibrewster's answer (including the external resource he linked to), here is the full set of instructions from that external page, with some added information to make this work with passwordless login and SELinux enforcing.

Reposting here in case the externally linked page happens to go away in the future.

These instructions apply to RHEL7 and CentOS7 (and perhaps other releases):

On the remote system:

First, add and configure the user account to be chrooted:

Note that the external resource used a different path for sftp-server. Be sure you have the correct path on your system or prepare yourself for pain. ;-) The path below works for a minimal install of RHEL7 & CentOS7.

# From command line:

groupadd sftponly    
useradd -d /home/$USERNAME -s /usr/libexec/openssh/sftp-server -M -N -g sftponly $USERNAME
mkdir -p /home/$USERNAME/uploads /home/$USERNAME/downloads /home/$USERNAME/.ssh
chown $USERNAME:sftponly /home/$USERNAME/uploads /home/$USERNAME/downloads /home/$USERNAME/.ssh
chown root /home/$USERNAME
chmod 755 /home/$USERNAME
chmod 700 /home/$USERNAME/.ssh
passwd $USERNAME
echo '/usr/libexec/openssh/sftp-server' >> /etc/shells

While I've set a password above, I will use passwordless login once I know the config works. Onward...

Assuming you have SELinux enabled and enforcing (you should), issue these commands to make it happy:

setsebool -P ssh_chroot_rw_homedirs on
restorecon -R /home/$USERNAME

Now, edit the sshd config as follows:

[root@remote]# vi /etc/ssh/sshd_config
#
# CHANGE lines: 
# 

# override default of no subsystems
#Subsystem      sftp    /usr/libexec/openssh/sftp-server    # commented out
Subsystem sftp internal-sftp                    # added

#
# ADD the following at the bottom: 
#

Match group sftponly
ChrootDirectory %h
AllowTcpForwarding no
ForceCommand internal-sftp

Finally, restart sshd

[root@remote]# systemctl restart  sshd.service

On the client system

First create the same account locally.

[root@client]# useradd -m $USERNAME
[root@client]# passwd $USERNAME
[root@client]# su $USERNAME

Ok now let's set up our RSA key pair.

[$USERNAME@client]# ssh-keygen

I wasn't able to get ssh-copy-id to work with the chroot config above, so I manually created the authorized_keys file with my client's id_rsa.pub text.

[$USERNAME@client]# cat .ssh/id_rsa.pub
---some key here---

Then back on the REMOTE system,

[root@remote]# vi /home/$USERNAME/.ssh/authorized_keys
---past key from right above, then wq---

Don't forget to set permissions on this file:

[root@remote]# chown $USERNAME:sftpusers  /home/$USERNAME/.ssh/authorized_keys

Ready to test

Everything should be in place now. From the client:

[$USERNAME@client]# sftp $USERNAME@remote

This should get you in. If you are prompted for a password (we haven't disabled PasswordAuthentication on the remote just yet), you have a configuration problem on the remote system. Scan your /var/log/secure for details.

If you sign on without being prompted for a password, you're almost finished.

Back on the remote system:

[root@remote]# vi /etc/ssh/sshd_config
# disable PasswordAuthentication
PasswordAuthentication no

# or optionally, just comment that line out

# PasswordAuthentication no
-- save and exit with :wq --

Restart sshd on the remote system:

[root@remote]# systemctl restart  sshd.service

Final test from Client

[$USERNAME@client]# sftp $USERNAME@remote
# in like Flynn?  yay!

Finished

You should be set to go with chroot sftp and passwordless login (with SELinux set to enforcing)