sftp gives permission denied only when chrooted?
Solution 1
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.
Solution 2
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)
Related videos on Youtube
![ibrewster](https://i.stack.imgur.com/c5kMw.jpg?s=256&g=1)
ibrewster
Coder by day, woodworker by night. Self-taught in Python, Javascript, HTML, CSS, and PostgreSQL over the past 11 years at my current position. Father of one cute son, husband to one cute wife. Looking to advance my career with a work-from-home development position.
Updated on September 18, 2022Comments
-
ibrewster almost 2 years
I have configured sshd_conf on my centos box as below:
Match group pilots ChrootDirectory /home/pilots ForceCommand internal-sftp X11Forwarding no AllowTcpForwarding no
and the directory /home/pilots like this:
# ls -al /home/pilots total 12 drwxr-x---. 3 root pilots 4096 Mar 10 14:20 . drwxr-xr-x. 7 root root 4096 Mar 10 14:10 .. drwxrwxr-x. 2 root pilots 4096 Mar 10 15:21 data -rwxrwxrwx. 1 root root 0 Mar 10 14:20 topLevel #
If I sftp in as a user in the pilots group WITHOUT the ChrootDirectory Directive enabled, I can cd to the /home/pilots folder (or a subdirectory thereof) and do a ls or get without difficulty. However, if I enable the ChrootDirectory directive, while I can still sftp in, and can cd to data, I can not do a ls or get in either directory. Trying ls, for example, gives a remote readdir("/"): Permission denied error, and trying to get topLevel gives File "/topLevel" not found. I was thinking maybe I wasn't in the directory I was expecting, but the ability to cd data would appear to indicate the chroot did work as intended.
looking at the messages log, I see the following when the ls is denied:
type=1400 audit(1394494944.504:50): avc: denied { read } for pid=22758 comm="sshd" name="pilots" dev=dm-0 ino=400504 scontext=unconfined_u:system_r:chroot_user_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:home_root_t:s0 tclass=dir
So there's a record of the denial. Still doesn't tell me why though.
What might I be doing wrong?
Couple of potentially important notes:
- The users in question exist on a remote LDAP server, accessed via sssd
- Access control must be by group, as many users will need read access to this same folder. Thus the ownership remaining root.
Edit: On further investigation, it appears this is related to SELinux - doing an
echo 0 >/selinux/enforce
fixes the issue, albeit in a kludgy, killing an ant with a sledgehammer kind of way. If possible, I'd like to know the "proper" fix. -
Matthew Moisen about 8 yearsUnfortunately, this didn't work for me; but disabling SELinux allows it to work.
-
a coder almost 8 yearsDisabling SELinux should never be a "fix" for configuration issues.
-
a coder almost 8 yearsThis answer (and the supplied link) was helpful - thanks. Just in case the referenced page becomes unavailable, I will repost it as an answer here (acknowledging yours as the correct answer for the question).
-
Fony Lew almost 3 yearsNice guide. Thank you!