# sftp/scp chroot solution?



## neurosis (Nov 24, 2010)

I have been struggling with this for two days. I had this working easily in a previous version of FreeBSD using scponly. I am not sure but it appears to be broken now. I can scp to the sshd but not sftp. It errors with "Cannot initialize SFTP protocol. Is the host running a SFTP server?"  

I have read several posts and threads regarding this problem but have not been able to come up with a solution. It appears that scponly now comes with a script that is to be run at start. I add it to my rc.conf and then try to run the script and this is what I get. 


```
# /usr/local/etc/rc.d/scponlyc start
sftptest/dev
mount: dev : Operation not permitted
/usr/local/etc/rc.d/scponlyc: WARNING: devfs_domount(): Unable to mount devfs on /home/sftptest/dev
devfs rule: ioctl DEVFSIO_RGETNEXT: Operation not permitted
```

Since I am only a FreeBSD user and not a power user I have no idea why I am getting this error. 

I also read that modern openssh includes a way to chroot users to their directory but I have not found any documentation explaining the process. I also see that it does it automatically if you have a /home/userdir/./ directory but I dont know how to create that.

Does anyone have any suggestions to help me get this working properly?

This is running inside of a jail btw but there are other things in the jail that I do not want the sftp/scp user to look at so I want them locked to their home dir.

this is FreeBSD 8.1-RELEASE


----------



## SirDice (Nov 24, 2010)

Have a look at the scponlyc startup script. It most likely tries to mount a devfs in the chroot environment. You cannot mount any filesystems within a jail so the mounting has to occur on the host. You can use the *jail_<jailname>_fstab* for this.


----------



## vermaden (Nov 24, 2010)

@neurosis

Like that mate:


```
/etc/group 
  chroot:*:999:

/etc/passwd 
  user:*:999:999:user:/data:/usr/sbin/nologin

/etc/ssh/sshd_config
  Match group          chroot
    ChrootDirectory    /home/%u
    X11Forwarding      no
    AllowTcpForwarding no
    ForceCommand       internal-sftp

# mkdir -p /home/user/data
# chown root:chroot /home/user
# chown user:chroot /home/user/data
```


----------



## neurosis (Nov 24, 2010)

@vermaden

I still get this error  "Cannot initialize SFTP protocol. Is the host running a SFTP server?"

I created two users to test this out.. I create one called storage and set up as a normal user. I can scp/sftp to this no problem (it works!) but it is obviously not chroot. 

So then I create a user (i hope) exactly as you said. I even called it "user".  I cannot sftp or scp to this account. I used winscp to test and I dont get much of an error message to re-post. 

I like the idea of chroot using your method if i can get it to work! 


@sirdice

You are correct. The script creates a /dev directory in the userdir and then mounts devfs inside of the jail. 

I dont understand how to use the <jails.fstab> to get this to work properly.. I dont know how to have it mount what it needs to I mean. 

Here is the script. 


```
# cat scponlyc
#!/bin/sh
#
# $FreeBSD: ports/shells/scponly/files/scponlyc.in,v 1.5 2010/03/27 00:14:50 dougb Exp $
#

# PROVIDE: scponlyc
# REQUIRE: LOGIN cleanvar
# KEYWORD: shutdown

# Add the following lines to /etc/rc.conf to enable scponly:
# scponlyc_enable (bool):               Set to "NO" by default.
#                                       Set it to "YES" to enable scponly
# scponlyc_shells (str):                Set to "/etc/shells" by default.
# scponlyc_passwd (str):                Set to "/etc/passwd" by default.

. /etc/rc.subr

scponlyc_shells="${scponlyc_shells:-/etc/shells}"
scponlyc_passwd="${scponlyc_passwd:-/etc/passwd}"

name="scponlyc"
rcvar=`set_rcvar`

start_cmd="scponlyc_startcmd"
stop_cmd="scponlyc_stopcmd"

required_files="$scponlyc_shells $scponlyc_passwd"

scponlyc=/usr/local/sbin/scponlyc

make_devfs() {
        # $1 is the user name whose home directory needs a minimal
        # devfs created. If ~/dev exists, it will be deleted.

        eval DEV="~$1/dev"
        if /sbin/mount | grep "${DEV}" >/dev/null 2>&1; then
                /sbin/umount "${DEV}" 2>/dev/null
        fi
        /bin/rmdir "${DEV}" || err 1 "Unable to remove $DEV"
        /bin/mkdir -p "${DEV}"
        devfs_domount "${DEV}"
        if devfs_init_rulesets; then
                devfs_apply_ruleset "devfsrules_hide_all" "${DEV}" && \
                devfs_apply_ruleset "devfsrules_unhide_basic" "${DEV}" || \
                /sbin/umount "${DEV}" 2>/dev/null
        fi
}

users_configured() {

        if [ `/usr/bin/grep -c "/scponlyc$" ${scponlyc_shells} 2>/dev/null` -ne 1 ]; then
                exit 1
        fi
}

scponlyc_startcmd() {

        users_configured

        /usr/bin/grep "^[^#]*:.*:.*:.*:.*:.*:${scponlyc}$" ${scponlyc_passwd} |
                /usr/bin/awk -F: {'print $1'} |
                while read USER; do
                        /bin/echo "${USER}/dev"
                        make_devfs "${USER}"
                done
}

scponlyc_stopcmd() {

        users_configured

        /usr/bin/grep "^[^#]*:.*:.*:.*:.*:.*:${scponlyc}$" ${scponlyc_passwd} |
                /usr/bin/awk -F: {'print $1'} |
                while read USER; do
                        /bin/echo "${USER}/dev"
                        eval DEV="~${USER}/dev"
                        /sbin/umount ${DEV} 2>/dev/null
                done
}

load_rc_config $name
run_rc_command "$1"
```


----------



## SirDice (Nov 24, 2010)

Assuming your jail is called "myjail" in /etc/rc.conf. Just create a /etc/fstab.myjail (on the host!) with something like:

```
devfs    /jail/myjail/usr/home/chroot/directory/dev     devfs    rw    0   0
```

These filesystems will get mounted/unmounted when the jail is started/stopped.


----------



## neurosis (Nov 24, 2010)

SirDice said:
			
		

> Assuming your jail is called "myjail" in /etc/rc.conf. Just create a /etc/fstab.myjail (on the host!) with something like:
> 
> ```
> devfs    /jail/myjail/usr/home/chroot/directory/dev     devfs    rw    0   0
> ...



SirDice! you are the man! It works very good! There should be a howto on this.  I have not been able to find any information on this unfortunately and it was so simple. 


Vermaden,

I would still like to know your method if you have time to explain better. That seems like it would be a better option as it uses the base system. 

Thanks guys.


----------



## SirDice (Nov 24, 2010)

neurosis said:
			
		

> SirDice! you are the man! It works very good! There should be a howto on this.  I have not been able to find any information on this unfortunately and it was so simple.



Have a look in /etc/defaults/rc.conf, there are more jail 'tricks'.

You can also add (if you need it)

```
jail_myjail_devfs_enable="YES"
```
That will mount a devfs on the jail's /dev/


----------



## vermaden (Nov 25, 2010)

neurosis said:
			
		

> @vermaden
> 
> I still get this error  "Cannot initialize SFTP protocol. Is the host running a SFTP server?"
> 
> ...



Here is how it looks connected:






... or by terminal:

```
% sftp user@host.com
Password:
Connected to host.com.
sftp> ls -l
drwxr-xr-x    2 999      999             2 Oct 28 05:25 data
sftp> pwd
Remote working directory: /
sftp> 
bye       cd        chdir     chgrp     chmod     chown     df        dir       exit      get       help      lcd       lchdir    lls       
lmkdir    ln        lpwd      ls        lumask    mkdir     progress  put       pwd       quit      rename    rm        rmdir     symlink   
version   !         ?         
sftp>
```

Have You restarted sshd(8) daemon after adding changes to its config file?
Have You set any password to the 'user' user?


----------



## rbelk (Nov 25, 2010)

Vermaden, I think the password entry wont work. Didn't you leave out a few entries? I think  it should look like this?

```
xfuser:*:999:999::0:0:xfuser/data:/usr/sbin/nologin
```
I did try your setup. The xfuser does connect without errors to the sftp subsystem, but my system is expecting password authentication. I did not give xfuser a password. Does the user have to generate SSH keys for authentication? I did restart sshd.


----------



## vermaden (Nov 25, 2010)

I forgot about */etc/master.passwd* file (# vipw in terminal)

```
/etc/master.passwd
  user:*:999:999::0:0:user:/data:/usr/sbin/nologin

/etc/passwd 
  user:*:999:999:user:/data:/usr/sbin/nologin
```

Now make user 'user' a password by # passwd user command in terminal.


----------



## neurosis (Nov 25, 2010)

vermaden said:
			
		

> Here is how it looks connected:
> 
> Have You restarted sshd(8) daemon after adding changes to its config file?
> Have You set any password to the 'user' user?



yes.. i restarted sshd and even restarted the jail. 

Let me post what i have done to make sure that I didnt miss anything. 

sshd_conf

```
Match group          chroot
   ChrootDirectory    /home/%u
   X11Forwarding      no
   AllowTcpForwarding no
   ForceCommand       internal-sftp
```

group


```
chroot:*:999:
```

passwd

```
user:*:999:999:user:/data:/usr/sbin/nologin
```

master.passwd


```
user:thereisapasswordherenow:999:999::0:0:user:/data:/usr/sbin/nologin
```


directories

```
# ls -al
total 12
drwxr-xr-x  3 root  chroot  512 Nov 26 01:12 .
drwxr-xr-x  4 root  wheel   512 Nov 26 00:45 ..
drwxr-xr-x  2 user  chroot  512 Nov 26 00:56 data
```

I still cant connect via sftp.  what did i miss?


----------



## vermaden (Nov 25, 2010)

@neurosis

Dunno mate, here is my /etc/ssh/sshd_config file:

(at least these line are not commented)


```
Subsystem       sftp    /usr/libexec/sftp-server

Match group chroot
   ChrootDirectory /home/%u
   X11Forwarding no
   AllowTcpForwarding no
   ForceCommand internal-sftp
```


----------



## neurosis (Nov 26, 2010)

vermaden said:
			
		

> @neurosis
> 
> Dunno mate, here is my /etc/ssh/sshd_config file:
> 
> ...



Yes... that line is not commented in my file too. sftp works if i create a normal user and do not try to chroot them in to their home directory. Im not sure what is going on. When I try to sftp in from a linux system it only tells me this. 


```
$ sftp user@host.com
Connecting to host.com...
Password:
Received message too long 1416128883
```

Then it ends..  yesterday I tried from a freebsd system and I got some strange authentication error. This is hard to track down..  I searched on google and seems that this error could be tied in to nologin? I havent found a solution.


----------



## neurosis (Nov 27, 2010)

@vermaden

I dont know what is going on, but i follow your steps exactly and it gives me errors. It acts as if the user account does not exist. 

```
# chown user:chroot /home/user/data/
chown: user: Invalid argument
```


```
# passwd user
passwd: user: no such user
```

I tried to set this up in the host system outside of the jail to see if the jail was causing an issue. I added the appropriate lines to the group, passwd, and master.passwd files. 

Not being able to figure this out is really bringing me down.. <grin> It seems like it should be very simple. I wonder if I should start a new topic regarding this?


----------



## neurosis (Nov 27, 2010)

Ok! I got it to work.  I changed the way that I created the user. Please explain to me why this works but I could not get it to work using your method. It does not make sense to me.  Here are the steps that I took. 

First I edited the sshd_config file to reflect the changes that you suggested and restarted sshd. 


```
/etc/ssh/sshd_config

Match group chroot
   ChrootDirectory /home/%u
   X11Forwarding no
   AllowTcpForwarding no
   ForceCommand internal-sftp

#/etc/rc.d/sshd restart
```

I then edited the group file (I was going to use pw groupadd but decided to just edit to keep your 999 GID) and added 


```
/etc/group
chroot:*:999:
```

I created the user as I would normally using adduser


```
# adduser
Username: user
Full name:
Uid (Leave empty for default):
Login group [user]: chroot
Login group is chroot. Invite user into other groups? []:
Login class [default]:
Shell (sh csh tcsh bash rbash scponly scponlyc nologin) [sh]: nologin
Home directory [/home/user]:
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]:
Use a random password? (yes/no) [no]:
Enter password:
Enter password again:
Lock out the account after creation? [no]:
Username   : user
Password   : *****
Full Name  :
Uid        : 1002
Class      :
Groups     : chroot
Home       : /home/user
Home Mode  :
Shell      : /usr/sbin/nologin
Locked     : no
OK? (yes/no): yes
adduser: INFO: Successfully added (user) to the user database.
Add another user? (yes/no): no
Goodbye!
```

Once the user was created I went to your steps for modifying home directory ownership. 


```
# mkdir -p /home/user/data
# chown root:chroot /home/user
# chown user:chroot /home/user/data
```

My passwd and master.passwd file looks a bit different. 


```
#/etc/passwd
user:*:1002:999:User &:/home/user:/usr/sbin/nologin

#/etc/master.passwd
user:wittypasswordhere:1002:999::0:0:User &:/home/user:/usr/sbin/nologin
```


I then sftp in to the users account and it worked!  the only difference is that it does not start in the /user/data directory. It logs in to the users home direcory. It is chroot in to that directory!  I really like this method! There should be a howto in the howto section for this! I would make one myself but I would not be able to answer any questions..  

I am not sure why this method worked and I could not get yours to work! I wish you could explain it to me! I dont understand what the difference is.


----------



## kpa (Nov 28, 2010)

Difference is that you edited /etc/passwd directly and didn't use  pwd_mkdb(8) to update etc/master.passwd. adduser(8) updated /etc/master.passwd automatically.


----------



## neurosis (Nov 28, 2010)

kpa said:
			
		

> Difference is that you edited /etc/passwd directly and didn't use  pwd_mkdb(8) to update etc/master.passwd. adduser(8) updated /etc/master.passwd automatically.




But rbelk or Vermaden did not use pwd_mkdb and were able to get this working. I would like to know why they were able to get this to work that way and I was not.


----------



## rbelk (Nov 28, 2010)

neurosis said:
			
		

> But rbelk or Vermaden did not use pwd_mkdb and were able to get this working. I would like to know why they were able to get this to work that way and I was not.



Neurosis, I edited the password file with vipw, it automatically runs pwd_mkdb. I also didn't get it to work either. After my trip home from Thanksgiving, I'll see what the problem is.


----------



## vermaden (Nov 28, 2010)

neurosis said:
			
		

> But rbelk or Vermaden did not use pwd_mkdb and were able to get this working. I would like to know why they were able to get this to work that way and I was not.



I user the *adduser* command, I just posted what should be in /etc/*passwd to make it work mate.


----------



## neurosis (Nov 30, 2010)

Ahhhh!  "forehead slap".   Thanks guys!


----------

