147

I want to give a client access to my server, but I want to limit those users to their home directories. I will bind-mount in any files I want them to be able to see.

I've created a user called bob and added him to a new group called sftponly. They have a home directory at /home/bob. I've changed their shell to /bin/false to stop SSH logins. Here is their /etc/passwd line:

bob:x:1001:1002::/home/bob:/bin/false

I've also changed the /etc/ssh/sshd_config to include the following:

Match Group sftponly
        ChrootDirectory /home/%u
        ForceCommand internal-sftp
        AllowTcpForwarding no

When I try to log in as them, here's what I see

$ sftp bob@server
bob@server's password: 
Write failed: Broken pipe
Couldn't read packet: Connection reset by peer

If I comment out the ChrootDirectory line I can SFTP in but then they have free rein over the server. I have found that ChrootDirectory /home works, but it still gives them access to any home directory. I have explicitly tried ChrootDirectory /home/bob but that doesn't work either.

What am I doing wrong? How can I limit bob to /home/bob/?

----EDIT-----

Okay so I just had a look at /var/log/auth.log and saw this:

May  9 14:45:48 nj sshd[5074]: pam_unix(sshd:session): session opened for user bob by (uid=0)
May  9 14:45:48 nj sshd[5091]: fatal: bad ownership or modes for chroot directory component "/home/bob/"
May  9 14:45:48 nj sshd[5074]: pam_unix(sshd:session): session closed for user bob

I'm not entirely sure what's going on there, but it suggests something is wrong with the user directory. Here is the ls -h /home output:

drwxr-xr-x 26 oli      oli      4096 2012-01-19 17:19 oli
drwxr-xr-x  3 bob      bob      4096 2012-05-09 14:11 bob
rm-vanda
  • 3,202
Oli
  • 299,380

5 Answers5

145

All this pain is thanks to several security issues as described here. Basically the chroot directory has to be owned by root and can't be any group-write access. Lovely. So you essentially need to turn your chroot into a holding cell and within that you can have your editable content.

sudo chown root /home/bob
sudo chmod go-w /home/bob
sudo mkdir /home/bob/writable
sudo chown bob:sftponly /home/bob/writable
sudo chmod ug+rwX /home/bob/writable

And bam, you can log in and write in /writable.

hennr
  • 213
Oli
  • 299,380
67

To chroot an SFTP directory, you must

  1. Create a user and force root to be owner of it

    sudo mkdir /home/john
    useradd -d /home/john -M -N -g users john
    sudo chown root:root /home/john
    sudo chmod 755 /home/john
    
  2. Change the subsystem location on /etc/ssh/sshd_config:

    #Subsystem sftp /usr/lib/openssh/sftp-server
    Subsystem sftp internal-sftp
    

    and create a user section at the end of the file (ssh can die respawning if placed after Subsystem line):

    Match User john
        ChrootDirectory %h
        ForceCommand internal-sftp
        AllowTCPForwarding no
        X11Forwarding no
    
rubo77
  • 34,024
  • 52
  • 172
  • 299
josircg
  • 1,259
  • 1
  • 16
  • 25
9

I spent the whole day trying to get a network share on my raspberry. I wanted to lock the user so that it would not be able to navigate through the whole file system, no ssh login access and I wanted to have write access to the network share.

And here is how I got it working:

First I created a user:

sudo useradd netdrive

Then edited /etc/passwd and made sure it has /bin/false for the user so the line was:

netdrive:x:1001:1004:Net Drive User,,,:/home/netdrive:/bin/false

I edited /etc/ssh/sshd_config to include:

Match User netdrive
  ChrootDirectory /home/netdrive
  ForceCommand internal-sftp
  AllowTcpForwarding no
  X11Forwarding no

Changed home directory owner and permissions:

sudo chown root:root /home/netdrive/
sudo chmod 755 /home/netdrive/

Ok so after all this I was able to connect using sshfs but in read only mode. What I had to do to get a writable folder:

sudo mkdir -p /home/netdrive/home/netdrive/
sudo chown netdrive:netdrive /home/netdrive/home/netdrive/
sudo chmod 755 /home/netdrive/home/netdrive/

That was it, it worked without any further changes. Note that I have only writable permissions to the user, not to the group as many other solutions online. I was able to create/delete/edit/rename files/folders without problems.

When accessing using sshfs with the netdrive user because of chroot configuration I would only see things stored inside server's /home/netdrive/ directory, perfect. The repeated /home/netdrive/home/netdrive/ directory structure is what made it work for me in having a clean chroot ssh writable solution.

Now I am going to explain below the problems I had:

You should probably not execute the following paragraphs:

After looking at the above solutions (and many others on the net which even used acl (access control lists)) I was still not able to get it working because what I did next was:

The following did NOT work for me:

sudo mkdir /home/netdrive/writable/
sudo chown netdrive:netdrive /home/netdrive/writable/
sudo chmod 755 /home/netdrive/writable/

Because the netdrive user was still not able to write in that /home/netdrive/writable/ directory despite owning the folder and having the permissions. Then I did: sudo chmod 775 /home/netdrive/writable/ And now I could create a directory and delete it but I was not able to edit it because it was being created without group writable permissions. Here from what I saw on the net people use acl to fix it. But I was not happy with that since it I had to install acl, then configure mount points, etc. Also I have no idea why I would need group permission to write to a folder owned by the same user.

It seems that for some reason creating /home/netdrive/home/netdrive and giving ownership to the last netdrive folder I was able to make everything work without messing with group permissions.

mihai.ile
  • 101
2

I followed this article but it didnt work. It started working after I made this change (suggested in above answers):

#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp

Plus made the root ownable home directory under which I had user writable sub directory (as described above).

The new and useful thing I want to add with this answer is that you can simplify the configuration simply by specifying %h as user home directory:

ChrootDirectory %h

I have discovered it thanks to this link.

0

I created a script from @Oli's answer:

#!/bin/bash

1. adds a user to the group sftponly, which have only access to their home directory

2. creates a writable folder in the users home directory

3. mounts a folder into the users home directory with bind

see https://askubuntu.com/questions/134425/how-can-i-chroot-sftp-only-ssh-users-into-their-homes

if [ "$1" == "" ]; then echo "usage: $0 [username] [path to share] [local foldername]" exit 0 fi U=$1

if [ "$2" == "" ]; then echo "no 2. param path to share given (without trailing slash)" exit 0 fi PATH_TO_SHARE="$2"

if [ "$3" == "" ]; then echo "no 3. param local foldername given" exit 0 fi LOCAL_FOLDER_NAME="$3"

set -ex

adduser $U adduser $U sftponly sudo chown root /home/$U sudo chmod go-w /home/$U sudo mkdir /home/$U/writable sudo chown $U:sftponly /home/$U/writable sudo chmod ug+rwX /home/$U/writable mkdir -p "/home/$U/$LOCAL_FOLDER_NAME/" mount --bind "$PATH_TO_SHARE/" "/home/$U/$LOCAL_FOLDER_NAME/"

echo "$PATH_TO_SHARE/ /home/$U/$LOCAL_FOLDER_NAME/ none defaults,bind 0 0">>/etc/fstab

rubo77
  • 34,024
  • 52
  • 172
  • 299