SFTP with chroot jail on CentOS
Posted by Stephan Kristyn on November 10th, 2010 / 23 Comments
SFTP which uses openssh was engineered by the IETF 2001-2007. It has the potential to replace the insecure and legacy FTP. Another alternative would be WebDAV. It seems like a great alternative to SFTP since it uses HTTP/TCP pipelining and should considerably speed up file transfers. However if you want WebDAV to be secure you would have go through the pain of creating a valid SSL connection.
SFTP should work out of the box if ssh is running on your server. Just connect from your client machine with
sftp [email protected]
The connection itself is tunneled over SSH now. However the user will have access to your entire file system and even worse if anyone gained these credentials, he could login via ssh to your server.
Since we don’t want that, we will have to chroot (jail root) the sftp user and forbid him to use ssh itself. For this you will need openSSH 5 or greater. At the time of this blog post, CentOS 5.5 still ships with the year old openSSH 4.6. Therefore we will have to make a rpm package with the latest openSSH 5.6 sources and install it on our CentOS.
rpm -qa | grep ssh
yum -y install gcc automake autoconf libtool make openssl-devel pam-devel rpm-build
wget http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/openssh-5.6p1.tar.gz
wget http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/openssh-5.6p1.tar.gz.asc
wget -O- http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/DJM-GPG-KEY.asc | gpg --import
gpg openssh-5.6p1.tar.gz.asc
tar zxvf openssh-5.6p1.tar.gz
cp openssh-5.6p1/contrib/redhat/openssh.spec /usr/src/redhat/SPECS/
cp openssh-5.6p1.tar.gz /usr/src/redhat/SOURCES/
cd /usr/src/redhat/SPECS/
perl -i.bak -pe 's/^(%define no_(gnome|x11)_askpass)\s+0$/$1 1/' openssh.spec
rpmbuild -bb openssh.spec
cd /usr/src/redhat/RPMS/`uname -i`
uname -i
ls -l
rpm -Uvh openssh*rpm
/etc/init.d/sshd restart
Alright what does all this command lines do? First yum installs the gnu compiler with important tools like make, then yum installs openssl development packages and rpm-build. Then I choose a repository from Aachen, Germany, which is nearest from my server’s location. We also get the gpg signature and import it to our local gpg databse then we check it. The rest is building the rpm package; without GUI support like X11 or gnome, because it’s not really usable on a server. I must credit some of these steps to someone else on the interwebs: http://binblog.info/2009/02/27/packaging-openssh-on-centos/
I found perl -i.bak -pe ‘s/^(%define no_(gnome|x11)_askpass)\s+0$/$1 1/’ openssh.spec to be very elegant and I liked also cd /usr/src/redhat/RPMS/`uname -i` very cool. The latter changes directory to the correct build version of your kernel.
Did I mention you should be root to do this?
I do it in one go, absolute hardcore.
rpm -qa | grep ssh && yum -y install gcc automake autoconf libtool make openssl-devel pam-devel rpm-build && wget http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/openssh-5.6p1.tar.gz && wget http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/openssh-5.6p1.tar.gz.asc && wget -O- http://ftp.halifax.rwth-aachen.de/openbsd/OpenSSH/portable/DJM-GPG-KEY.asc | gpg --import && gpg openssh-5.6p1.tar.gz.asc && tar zxvf openssh-5.6p1.tar.gz && cp openssh-5.6p1/contrib/redhat/openssh.spec /usr/src/redhat/SPECS/ && cp openssh-5.6p1.tar.gz /usr/src/redhat/SOURCES/ && cd /usr/src/redhat/SPECS/ && perl -i.bak -pe 's/^(%define no_(gnome|x11)_askpass)\s+0$/$1 1/' openssh.spec && rpmbuild -bb openssh.spec && cd /usr/src/redhat/RPMS/`uname -i` && uname -i && ls -l && rpm -Uvh openssh*rpm
Better check if it worked.
rpm -qa | grep ssh
openssh-clients-5.6p1-1
openssh-5.6p1-1
openssh-server-5.6p1-1
This were the pre-requisites for using chroot with SFTP. I will show how to setup SFTP and prepare your directory structure.
First, setup two new groups. One group fullssh is going to have full access to the Linux filesystem. Just add your main user to the fullssh supplementary group. The other group is called sftponly for our SFTP users that will be jailed to a particular directory.
groupadd sftponly
useradd pete
usermod -aG sftponly pete
In above snippet one could also use useradd -G sftponly pete, but in case the user pete exists already the -a switch ensures he is added to the supplemental group sftponly instead of deleting existing supplemental groups.
Now go into /etc/ssh/sshd_config and comment out the default entry for the sftp service.
#Subsystem sftp /usr/lib64/misc/sftp-server
Subsystem sftp internal-sftp
AllowGroups fullssh sftponly
Match Group sftponly
ChrootDirectory /var/www/html
ForceCommand internal-sftp
X11Forwarding no
AllowTcpForwarding no
Now let’s set permissions on the directory structure. This has to be done with great care.
chown root:sftponly /var/www/html
chmod 755 /var/www/html
mkdir -p /var/www/html/yourDomain
chown pete:sftponly /var/www/html/yourDomain
Some tutorials on the web suggest setting permissions to 750, but as it turns out this will lock out apache and produces a HTTP 403 Forbidden when accessing your website. We don’t want that.
With chown you change the owners of the directory to root user-wise and to sftponly group-wise. The user pete should be a member of that group by now. You can check that with groups pete.
Creating the directory with the -p shouldn’t be necessary in above example, but I included it nonetheless. The switch would take care of creating all necessary parent folders.
This is how the permissions must look like in order to make the ssh / sftp login chain to work.
ls -lishad /var/www/html
inode 4.0K drwxr-xr-x 3 root sftponly 4.0K Nov 9 10:27 /var/www/html
ls -lishad /var/www/html/yourDomain
inode 4.0K drwxr-xr-x 8 joe sftponly 4.0K Nov 9 11:33 /var/www/html/yourDomain
Now if you login, ssh has root permissions and handles the login process until the user pete is authenticated. The user is then jail chrooted to the yourDomain directory, at least in my understanding. With SFTP we don’t need a proper chroot environment with access to /dev or any hardlinks – therefore it should be rather difficult for an attacker to escape the jail. There exists an exploit [1] since 1999. That is why Solaris and Linux stopped to consider chroot a secure solution. However it is possible to harden [2] a shell chroot environment.
I hope you enjoyed this article. I would appreciate any thoughts on the topic of server security in the comments below.
References
http://www.bpfh.net/simes/computing/chroot-break.html
[2] chroot HowTo
http://debian.chains.ch/chroot/chroot.html
http://v2.robbyt.com/2008/howto/chrooted-sftp-with-openssh-5/
Twitter
Facebook
Reddit
StumbleIt!
Digg it
Google
Delicious
Comments
-
Comment by tim on Jan 21st, 2011 at 2 pm
what would you have to modify for users of sftponly group to have write permissions in /var/www/html/yourDomain ?
-
Comment by admin on Jan 21st, 2011 at 2 pm
Dear tim, it seems like I made a typo in the line
“chown pete:sftponly /var/www/yourDomain”. The correct line would be: “chown pete:sftponly /var/www/html/yourDomain”.If you want to give the group sftponly write permissions to that folder and its subfolders just do a “chmod 775 -R /var/www/html/yourDomain” or “chmod sftponly+w …”.
-
Comment by tim on Jan 21st, 2011 at 6 pm
would those rules not be to loose for files ? Normally it is recommended 755 for directories and 644 for files so for sftponly group: 775 for directories and 664 for files:
find . -type d -exec chmod 775 {} \;
find . -type f -exec chmod 664 {} \; -
Comment by admin on Jan 22nd, 2011 at 8 am
Well I don’t know of the recommendations, I use my own logic. 6 in the decimal system equals the read and write bit, therefore your files like php were not executable for the user under which apache is running on. Or am I missing something?
-
Comment by tim on Jan 22nd, 2011 at 10 am
here is the joomla advice/explanation:
http://docs.joomla.org/How_do_UNIX_file_permissions_work%3FBut you are correct that for some applications rights have to be different. In my case they have to be 775 and 664 for my sftponly users to be able upload files and list the directory.Ownership is www-data:sftponly .But evertyhing is working ok now thanks to websites like yours that help understand how to make it all work…
-
Comment by Chris on Apr 12th, 2011 at 7 pm
Didn’t work. My system still thinks it has openssh version 4.3 installed.
-
Comment by admin on Apr 13th, 2011 at 3 pm
Chris, it worked twice for me. Make sure the rpm got correctly build and then installed.
-
Comment by Chris on Apr 13th, 2011 at 3 pm
How do I know if either of these parameters were met? I saw no error messages.
Does my system need ssh 4.6 as a prerequisite?
-
Comment by admin on Apr 13th, 2011 at 3 pm
Yes, you need some version of openSSL installed first, since I used the ‘update’ switch with rpm above. (rpm -Uvh)
man rpm
rpm {-U|–upgrade} [install-options] PACKAGE_FILE …
This upgrades or installs the package currently installed to a newer version. This is the same as install, except all other version(s) of the package are removed after the new package is installed.
-
Comment by Chris on Apr 13th, 2011 at 3 pm
I meant does this install require 4.6 SSH as the native install of CentOS 5.5 comes with 4.3 SSH.
I noticed this upgrade did not create any KEY files either. It must have blown up somewhere that I could not see. I am rebuilding this server with CentOS 5.6 right now but I see the SSH version included is still only 4.3
I will give it another try. -
Comment by admin on Apr 13th, 2011 at 4 pm
Well, yes, as I wrote in my tutorial, I got 4.6 running at my CentOS before doing the upgrade. Keyfiles are mandatory to any openSSL installation and I assumed you have them already.
-
Comment by Chris on Apr 13th, 2011 at 4 pm
I do have keyfiles but for openSSH4.3
I see no where in your tutorial that you upgraded openSSH 4.3 to 4.6.I found this when re-running each command:
gpg openssh-5.6p1.tar.gz.asc
gpg: Signature made Sun 22 Aug 2010 11:24:54 PM EDT using DSA key ID 86FF9C48
gpg: Good signature from “Damien Miller (Personal Key) ”
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 3981 992A 1523 ABA0 79DB FC66 CE8E CB03 86FF 9C48Any thoughts?
-
Comment by Chris on Apr 13th, 2011 at 7 pm
Th error keeping me from updating:
error: Failed dependencies:
openssh = 4.3p2-72.el5 is needed by (installed) openssh-askpass-4.3p2-72.el5.x86_64
openssh = 4.3p2-72.el5 is needed by (installed) openssh-server-4.3p2-72.el5.x86_64
openssh = 4.3p2-72.el5 is needed by (installed) openssh-clients-4.3p2-72.el5.x86_64I’m dead in the water at this point.
-
Comment by admin on Apr 13th, 2011 at 7 pm
-
Comment by Chris on Apr 13th, 2011 at 8 pm
Got it…by using –nodeps while upgrading the package. I now show a fully upgraded SSH.
phew!
-
Comment by admin on Apr 13th, 2011 at 10 pm
Perfect! Thanks for letting us know, how you solved your problem. Cheers!
-
Pingback by Jail time: CentOS 5.6 + OpenSSH SFTP Chroot jails | Virtual Knuckles on Aug 8th, 2011 at 10 pm
[...] OpenSSH first before we configure our jails. We’ll be doing this from source. Thanks to http://meshfields.de/sftp-chroot-centos/ and [...]
-
Comment by millsy on Aug 21st, 2011 at 3 pm
Great tutorial – I’ve got Chrooted users working fine, but the FTP client then stops reporting the actual name and group of the owner – instead it only reports the uid and the gid. Removing the jail returns the name and group as normal but allows the user access to the whole filesystem. Have you noticed this?
-
Comment by Dave on Sep 30th, 2011 at 11 pm
I tried this with Fedora 2.6.40.4-5.fc15.i686.PAE and OpenSSH_5.6p1, OpenSSL 1.0.0e-fips and every time I try to put as pete I get:
Uploading /tmp/testfile to /upload/testfile
remote open(“/upload/testfile”): Permission deniedsshd_config
Subsystem sftp internal-sftp
AllowGroups fullssh sftponlyMatch Group sftponly
ChrootDirectory /usr/newdir/sftpdir
ForceCommand internal-sftp
X11Forwarding no
AllowTcpForwarding noMy chroot path is /usr/newdir/sftpdir
1316546 4.0K drwxr-xr-x. 3 root sftponly 4.0K Sep 30 16:37 /usr/newdir/sftpdir/and a subdir of upload
1316549 4.0K drwxrwxr-x. 2 pete sftponly 4.0K Sep 30 16:37 /usr/newdir/sftpdir/uploadWe’re setting this up new so the installs are all fresh; no updates/upgrades. Even when I try to login as another user(not in group sftponly) I can not put even though the user goes to its home(/home/user) directory.
We did not install openssh the same way you did. We just installed through the GUI installer.
rpm -qa | grep ssh
openssh-server-5.6p1-34.fc15.1.i686
libssh2-1.2.7-1.fc15.i686
openssh-clients-5.6p1-34.fc15.1.i686
openssh-5.6p1-34.fc15.1.i686Any ideas? Every article/blog I see has pretty much the same simple instructions but I keep getting the same results so it must be something I’m doing here.
-
Comment by Adam on Jan 16th, 2012 at 11 pm
Thanks for the help, one question how do I set the default file permissions for uploads?
-
Comment by John Peden on Apr 27th, 2012 at 1 pm
Worked an absolute treat for me, thanks for the tut.
I ran into a failed dependency just before installing the new rpms but simply ran yum remove openssh-askpass to get around.
-
Pingback by ssh Benutzer im Ordner einsperren « itbasic on Oct 11th, 2012 at 8 am
[...] Ich bin nach dieser Anleitung vorgegangen: http://meshfields.de/sftp-chroot-centos/ [...]
-
Comment by Pascual on Mar 20th, 2013 at 12 pm
Great tutorial, but on a sidenote after logging in via sftp the user is jailed in the html directory instead of his own folder and actually can see other folders in the html directory. Is it possibly to totally jail them in their directory?
Thanks
