So, you want to setup an SFTP server that will not allow your users to do any of the other things that ssh would normally allow (like a shell) and you don't want them to be able to look all around your server and read any world readable file. You found the ChrootDirectory setting in man sshd_config but it didn't just work because you can't chroot a user to their home directory because the chroot directory has to be owned by root and only writable by root. Well duh, it is called chroot not chhomedir. The user's home directory is supposed to be inside of the chroot not the root of it. The good news is that this is completely possible to accomplish with a few tricks.
Note: This is written specifically for OpenSSH on Linux. It is not distribution specific but other operating systems will probably need some syntax changes.
Also, I am assuming you know how to add a user to your OS/distro.
Also, This will NOT allow scp. Only sftp.
Also, This will NOT allow rsync either. If you want to use rsync you can skip all of this and use rrsync to restrict the user.
Also, If you are doing this to allow users to upload a web site to a web server you are probably wasting your time. If your web server allows any kind of scripting (PHP, perl, python, etc) then it will be trivial for the user to upload a script that will do whatever they want without the chroot restrictions. Unless of course the web server is also chrooted which is a much more complicated setup.
First, let's setup the /etc/ssh/sshd_config file. We are going to use a group called sftp-only to denote which users these settings will apply to. You can list the users if you wish instead but using a group makes it pretty easy as you can tell adduser/useradd to set the account up in that group initially. You need to add a Match block to apply different settings to users in the sftp-only group:
Match Group sftp-only ChrootDirectory /chroots/%u X11Forwarding no AllowTcpForwarding no ForceCommand internal-sftp
Note: you do not need to change the Subsystem sftp line to internal-sftp. Doing so can actually have security implications for non-matched users (internal-sftp works even if the user does not have a valid $SHELL while the external one runs under the user's $SHELL).
I know, you are screaming "But my users are in /home/%u not /chroots/%u!". Well, this is where things get interesting but require a bit of per-user work. For each $UserName that will use this setup perform the following steps:
mkdir -p /chroots/$UserName/home/$UserName chown root:sftp-only /chroots /chroots/$UserName /chroots/$UserName/home /chroots/$UserName/home/$UserName chmod 0750 /chroots /chroots/$UserName /chroots/$UserName/home /chroots/$UserName/home/$UserName echo "/home/$UserName /chroots/$UserName/home/$UserName bind defaults,bind 0 0" >> /etc/fstab mount -v /chroots/$UserName/home/$UserName
Now, when the user logs in via SFTP the authentication phase is run against their normal /home/$UserName allowing them to have a ~/.ssh/authorized_keys file. As soon as they authenticate they are chrooted to /chroots/$UserName. The internal-sftp service is then launched placing them in their home directory /home/$UserName within the chroot. Their home directory will look the same to them with or without the chroot. The only difference is that if they cd out of their home directory they will see a filesystem that contains nothing else.
You can also optionally setup /etc/passwd and /etc/group files within the /chroots/$UserName directory if you want to make ls -l look right in the sftp client. It doesn't need real data it just needs to map the appropriate UIDs and GIDs to the names you want displayed in the ls -l output.
Here is an example setup (the commands marked optional are purely cosmetic):
desktop# tail /etc/ssh/sshd_config Match Group sftp-only ChrootDirectory /chroots/%u X11Forwarding no AllowTcpForwarding no ForceCommand internal-sftp desktop# groupadd sftp-only desktop# useradd --comment "chroot demo account" --home-dir /home/sftpuser --group sftp-only --create-home --shell /sbin/nologin sftpuser desktop# getent passwd sftpuser sftpuser:x:12320:12321:chroot demo account:/home/sftpuser:/sbin/nologin desktop# mkdir -p /chroots/sftpuser/home/sftpuser # setup an authorized_keys file now if you want. desktop# chown -R root:sftp-only /chroots desktop# chmod 710 /chroots desktop# chmod -R 750 /chroots/sftpuser desktop-optional# mkdir /chroots/sftpuser/etc desktop-optional# chgrp sftp-only /chroots/sftpuser/etc desktop-optional# chmod 710 /chroots/sftpuser/etc desktop-optional# getent passwd sftpuser > /chroots/sftpuser/etc/passwd desktop-optional# echo "root:x:0:0:not really root:::" >> /chroots/sftpuser/etc/passwd desktop-optional# chmod 644 /chroots/sftpuser/etc/passwd desktop-optional# getent group sftp-only > /chroots/sftpuser/etc/group desktop-optional# getent group sftpuser >> /chroots/sftpuser/etc/group desktop-optional# chmod 644 /chroots/sftpuser/etc/group desktop# echo "/home/sftpuser /chroots/sftpuser/home/sftpuser bind defaults,bind 0 0" >> /etc/fstab desktop# mount -v /chroots/sftpuser/home/sftpuser /home/sftpuser on /chroots/sftpuser/home/sftpuser type none (rw,bind) desktop# passwd sftpuser New password: Retype new password: passwd: password updated successfully -------------------------------------------------------------------------------------------------------------------- How it looks to the user if you set it up this way... -------------------------------------------------------------------------------------------------------------------- kmk@desktop[1%]> sftp sftpuser@localhost Connected to localhost. sftp> pwd Remote working directory: /home/sftpuser sftp> ls -la drwxr-xr-x 3 sftpuser sftpuser 1024 Oct 3 00:47 . drwxr-x--- 3 root sftp-only 1024 Oct 3 00:47 .. -rw-r--r-- 1 sftpuser sftpuser 127 Aug 19 20:10 .bash_logout -rw-r--r-- 1 sftpuser sftpuser 193 Aug 19 20:10 .bash_profile -rw-r--r-- 1 sftpuser sftpuser 551 Aug 19 20:10 .bashrc drwx------ 2 sftpuser sftpuser 1024 Sep 16 2007 .ssh -rw-r--r-- 1 sftpuser sftpuser 1466 Sep 20 2003 .tcsh.config sftp> cd .. sftp> ls -la drwxr-x--- 3 root sftp-only 1024 Oct 3 00:47 . drwxr-x--- 4 root sftp-only 1024 Oct 3 00:48 .. drwxr-xr-x 3 sftpuser sftpuser 1024 Oct 3 00:47 sftpuser sftp> cd .. sftp> ls -la drwxr-x--- 4 root sftp-only 1024 Oct 3 00:48 . drwxr-x--- 4 root sftp-only 1024 Oct 3 00:48 .. drwx--x--- 2 root sftp-only 1024 Oct 3 00:49 etc drwxr-x--- 3 root sftp-only 1024 Oct 3 00:47 home sftp> cd .. sftp> ls -la drwxr-x--- 4 root sftp-only 1024 Oct 3 00:48 . drwxr-x--- 4 root sftp-only 1024 Oct 3 00:48 .. drwx--x--- 2 root sftp-only 1024 Oct 3 00:49 etc drwxr-x--- 3 root sftp-only 1024 Oct 3 00:47 home sftp> cd etc sftp> ls -la remote readdir("/etc"): Permission denied sftp>