Previous Entry Share
How to setup openssh chrooted sftp and SELinux in Fedora 16
updated: 2012-02-10
I promised that I would write an article about setting of the chrooted sftp accounts with openssh and SELinux. So here it is.


I use Fedora 16 but everything I write is applicable in later Fedoras either since openssh-5.8p2-24.fc16 and later contain SELinux support for chrooted sftp environment.

openssh server configuration

I don't want to restrict all users, so I prepare special group for restricted users called sftponly:
server# groupadd sftponly
Then I add these lines to /etc/ssh/sshd_config file:
 Match Group sftponly
     ForceCommand internal-sftp
     ChrootDirectory %h
It means if an user is in the group sftponly, force internal-sftp for him and chroot him into his home directory. Then that restart sshd service:
server# systemctl restart sshd.service

user configuration

server# useradd -M -g sftponly sftponlyuser
This command creates the "sftponlyuser" user with home direcotry set to /home/sftponlyuser, but this directory is not created. This directory will be used as root for chrooted sftp sessions and has to be owned by root and not be writeable by anybody else. But subdirectory for upload must be owned by sftponlyuser:
updated: 2012-02-10
server# mkdir -p /home/sftponlyuser/upload

server# chown sftponlyuser: /home/sftponlyuser/upload

server# restorecon -R -v /home/sftponlyuser
restorecon reset /home/sftponlyuser context unconfined_u:object_r:home_root_t:s0->unconfined_u:object_r:user_home_dir_t:s0
restorecon reset /home/sftponlyuser/upload context unconfined_u:object_r:home_root_t:s0->unconfined_u:object_r:user_home_t:s0
Now I try to connect with sftp to the sftponlyuser account
client$ sftp sftponlyuser@f16-openssh
Connecting to f16-openssh...
sftponlyuser@f16-openssh's password: password
sftp> ls
sftp> cd upload
It looks good.


sftp> put myfile.txt
Uploading myfile.txt to /upload/myfile.txt
Couldn't get handle: Permission denied
All chrooted sftp processes are running as the chroot_user_t context:
system_u:system_r:chroot_user_t:s0-s0:c0.c1023 \_ sshd: sftponlyuser@notty
system_u:system_r:chroot_user_t:s0-s0:c0.c1023      \_ sshd: sftponlyuser@internal-sftp
And there is an AVC message on the server:
type=AVC msg=audit(1328793486.912:654): avc:  denied  { write } for  pid=12722 comm="sshd" name="upload" dev=vda3 ino=971 scontext=system_u:system_r:chroot_user_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=dir
chroot_user_t can be allowed to write into user_home_t using the SELinux boolean 'ssh_chroot_rw_homedirs'
server# setsebool -P ssh_chroot_rw_homedirs on
sftp> put myfile.txt
Uploading myfile.txt to /upload/myfile.txt
myfile.txt                                        100%   29     0.0KB/s   00:00
Moreover, chroot_user_t is also restricted in read operations. This context is allowed to read only contexts intended for user home content:
updated: 2012-02-10
server# echo 'secret data' > ~sftponlyuser/upload/secret_file.txt

server# chcon -t admin_home_t ~sftponlyuser/upload/secret_file.txt

server# cp /etc/passwd /home/sftponlyuser/upload

server# chcon -t etc_t /home/sftponlyuser/upload/passwd                                                                       
sftp> ls
sftp> get secret_file.txt
Couldn't stat remote file: Permission denied
File "/upload/secret_file.txt" not found.

sftp> get passwd
Couldn't stat remote file: Permission denied
File "/upload/passwd" not found.
server# setenforce 0
sftp> ls
myfile.txt     passwd      secret_file.txt

sftp> get secret_file.txt
Fetching /upload/secret_file.txt to secret_file.txt
/upload/secret_file.txt                           100%   12     0.0KB/s   00:00


  • 1

You may need to: sudo restorecon -R -v /home/sftponlyuser

Hardcoding types is less nice:

+ ssh_selinux_change_context("chroot_user_t");

I've updated text with restorecon and added another example with etc_t



Thanks for this post, it's very interesting!

By following your instructions, I was able to setup successfully chrooted sftp on Fedora 16.

But it fails on CenOS 6.2 when selinux is enabled:
setsebool -P ssh_chroot_rw_homedirs on
libsemanage.dbase_llist_set: record not found in the database

Any suggestion?

What is your selinux-policy package version? You need selinux-policy-3.7.19-109.el6 at least.

System is fully updated,
[root@localhost ~]# rpm -q selinux-policy

Maybe the selinux boolean has a different name ?

[root@localhost ~]# getsebool -a | grep ssh
allow_ssh_keysign --> off
sftpd_write_ssh_home --> off
ssh_sysadm_login --> off

[root@localhost ~]# getsebool -a | grep sftp
sftpd_anon_write --> off
sftpd_enable_homedirs --> off
sftpd_full_access --> off
sftpd_write_ssh_home --> off

There is probably something broken in your installation or maybe in centos. ssh_chroot_rw_homedirs exists in in RHEL-6.2 - selinux-policy-3.7.19-126.el6_2.10.noarch - and also in scientific linux - selinux-policy-3.7.19-126.el6_2.6.noarch.

You can try to re-install selinux-policy-targeted:
# yum reinstall selinux-policy-targeted

I've checked on another Centos-6 install, and ssh_chroot_rw_homedirs does indeed exist. Reinstalling selinux-policy-targeted didn't help, but that's just a virtual machine for testing, no worry.
Thanks again for your tutorial and your kind assistance.

  • 1

Log in