Results 1 to 10 of 109

Thread: Howto create chrooted Openssh SFTP without shell access through rssh.

Threaded View

  1. #1
    Join Date
    Nov 2005
    Ubuntu 6.06

    Post Howto create chrooted Openssh SFTP without shell access through rssh.

    This functionality now comes standard in OpenSSH using the ChrootDirectory and the ForceCommand keyword in sshd_config! Hurray!

    The Match keyword also allows you to specify which users are affected. This means that rssh and the setup outlined in this howto are no longer necessary. From the sshd_config man page:
                 Specifies a path to chroot(2) to after authentication.  This
                 path, and all its components, must be root-owned directories that
                 are not writable by any other user or group.
                 The path may contain the following tokens that are expanded at
                 runtime once the connecting user has been authenticated: %% is
                 replaced by a literal '%', %h is replaced by the home directory
                 of the user being authenticated, and %u is replaced by the user‐
                 name of that user.
                 The ChrootDirectory must contain the necessary files and directo‐
                 ries to support the users' session.  For an interactive session
                 this requires at least a shell, typically sh(1), and basic /dev
                 nodes such as null(4), zero(4), stdin(4), stdout(4), stderr(4),
                 arandom(4) and tty(4) devices.  For file transfer sessions using
                 “sftp”, no additional configuration of the environment is neces‐
                 sary if the in-process sftp server is used (see Subsystem for
                 The default is not to chroot(2).
                 Forces the execution of the command specified by ForceCommand,
                 ignoring any command supplied by the client and ~/.ssh/rc if
                 present.  The command is invoked by using the user's login shell
                 with the -c option.  This applies to shell, command, or subsystem
                 execution.  It is most useful inside a Match block.  The command
                 originally supplied by the client is available in the
                 SSH_ORIGINAL_COMMAND environment variable.  Specifying a command
                 of “internal-sftp” will force the use of an in-process sftp
                 server that requires no support files when used with
         Match   Introduces a conditional block.  If all of the criteria on the
                 Match line are satisfied, the keywords on the following lines
                 override those set in the global section of the config file,
                 until either another Match line or the end of the file.
                 The arguments to Match are one or more criteria-pattern pairs.
                 The available criteria are User, Group, Host, and Address.  The
                 match patterns may consist of single entries or comma-separated
                 lists and may use the wildcard and negation operators described
                 in the PATTERNS section of ssh_config(5).
                 The patterns in an Address criteria may additionally contain
                 addresses to match in CIDR address/masklen format, e.g.
                 “” or “3ffe:ffff::/32”.  Note that the mask length
                 provided must be consistent with the address - it is an error to
                 specify a mask length that is too long for the address or one
                 with bits set in this host portion of the address.  For example,
                 “” and “” respectively.
                 Only a subset of keywords may be used on the lines following a
                 Match keyword.  Available keywords are AllowAgentForwarding,
                 AllowTcpForwarding, Banner, ChrootDirectory, ForceCommand,
                 GatewayPorts, GSSAPIAuthentication, HostbasedAuthentication,
                 KbdInteractiveAuthentication, KerberosAuthentication,
                 MaxAuthTries, MaxSessions, PasswordAuthentication,
                 PermitEmptyPasswords, PermitOpen, PermitRootLogin,
                 RhostsRSAAuthentication, RSAAuthentication, X11DisplayOffset,
                 X11Forwarding and X11UseLocalHost.
    You should probably use the functionality built into OpenSSH instead, but just in case you don't want to do so, below is the tutorial as it was, which was last edited on February 5th, 2008 at 08:10 PM.

    Howto create chrooted Openssh SFTP without shell access through rssh.

    I noticed many people wanted to set up a secure way (non cleartext and authentication required) to transfer files but wanted to limit their users from accessing a shell or browsing the entire file system. For the past week, I have been searching for a way to do this myself.

    However, most of the solutions posted to these requests didn't suit me: chrootssh (, which I found difficult to set up since it involved compiling from source instead of installing from a package; set up another ftp server (like vsftpd), since I already had sshd running, I didn't want to manage another server and I was having difficulty getting this to work securely; setting the user's shell to the sftp-server, which still allowed to user to get out of their directories (but limited the user to sftp).

    I also tried rssh unsuccessfully once before finding a HOWTO from the gentoo-wiki website < hout_shell)&redirect=no>. (Many thanks to them). I adapted their HOWTO slightly to work for Ubuntu.

    It took me a week to finally set it up and get it working since I started trying. I hope this HOWTO will help anyone else who wants to do this, but since I am writing this HOWTO after I set it up, I may accidentally forget a step. In addition, my system may differ from your's (FYI, Ubuntu Breezy with i686 kernel; but even if you have the same, your configs may differ). I make no guarantees that this will work on your system. I am just writing this in hopes that it will help. Feel free to post any suggestions/comments/questions/corrections. NOTE: I only tested my setup for SFTP.

    First, you need the "openssh-server" package. (I assume you already have that installed, updated, and configured. If not, it is pretty easy to do so & there are other tutorials available. You can get it through Synaptic Package Manager.)

    Then get the "rssh" package through Synaptic or through apt-get.

    Once that is ready, you can configure rssh by editing the file "/etc/rssh.conf". (You probably want to make a backup copy of that file by typing the command:
    sudo cp /etc/rssh.conf /etc/rssh.orig.conf
    The command I used to edit /etc/rssh.conf was :
    sudo nano /etc/rssh.conf
    Note: you need the nano text editor to do this. replace "nano" with "gedit" or another text editor if you want.

    The file should already be mostly filled out. Just uncomment (by removing the '#') the lines "#allowsftp" to allow sftp and if you want, uncomment the line "#allowscp". I left "#allowscp" commented since I only wanted sftp.

    There should be a line in "/etc/rssh.conf" that currently reads:
    #chrootpath = "/usr/local/chroot dir"
    change it to:
    chrootpath = "/home/chroot"
    (uncomment the line and change the path to "/home/chroot". The path is personal preference, but I decided "/home/chroot".) Doing this tells rssh to chroot jail everyone using rssh to the directory "/home/chroot".

    At this point, your rssh.conf file should have the following uncommented lines:
    logfacility = LOG_USER
    umask = 022
    chrootpath = "/home/chroot"
    Now to make sure OpenSSH does not weaken rssh (gunzip and read "/usr/share/doc/rssh/SECURITY" for more information), make sure you have the latest package for openssh-server and run the following command:
    cat /etc/ssh/sshd_config | grep "PermitUserEnvironment"
    If you see the line beginning with "PermitUserEnvironment", use your text editor to either remove the line from "/etc/ssh/sshd_config" or to change the line to
    Now to build the chrooted directory. There should be a zipped script at "/usr/share/doc/rssh/examples/". Unzip the file, make a copy and edit the copy. You can do so using the following series of commands
    sudo gunzip /usr/share/doc/rssh/examples/
    sudo cp /usr/share/doc/rssh/examples/ ~/
    sudo nano ~/mkchroot
    If you scroll through the file, you will find the lines:
    Make sure these paths match the ones given when you type the following command:
    rssh -v
    If they do not match, change your script so the paths match.

    If your setup is like mine, your sftp server will actually be located in "/usr/lib/openssh/sftp-server" instead of "/usr/lib/sftp-server", which is where rssh thinks the sftp-server is. If this is your case, change
    Save the script and exit the editor.

    Then make the script executable with the following command:
    sudo chmod u+x ~/

    Now remember how you made
    chrootpath = "/home/chroot"
    in "/etc/rssh"? Well, now you actually make the chroot directory by running the following commands:
    cd ~
    sudo ./ /home/chroot
    While running that command, don't worry if you get the error saying that it cannot copy "". It isn't a real file. However, you will probably need to copy the file "" if it appears when you type the command:
    ldd /usr/bin/scp | grep ""
    but is not in the path "/home/chroot/lib/". You can copy the file with the following commands:
    cd /home/chroot
    sudo cp /lib/ lib/
    Just to play it safe, make sure you have "" in the directory "/home/chroot/lib". If not, put it there with the following command:
    sudo cp /lib/ /home/chroot/lib/
    Now make rssh a valid shell by running the command:
    add-shell /usr/bin/rssh
    Now create a new user (I called mine "sft" for secure file transfer). Make the shell for the new user "/usr/bin/rssh". Make sure the home directory path is inside the chroot jail. For me, I made the home directory "/home/chroot/home/sft". If you don't know how to add a user, there is a GUI under System -> Administration -> Users and Groups.

    Now to apply the finishing touches and tie up loose ends:

    For logging to work properly, you need to tell sysklogd to listen to "/home/chroot/dev/log". You can do this by editing "/etc/init.d/sysklogd".
    WARNING: You can seriously mess up your system logging if you mess up here. BE CAREFUL!
    (you can replace nano with your text editor of choice). Run the following to edit "/etc/init.d/sysklogd":
    sudo nano /etc/init.d/sysklogd
    You should find a line that starts with:
    Simply add the following in the appropriate space on the line:
    -a /home/chroot/dev/log
    If your config is like mine, the original line will read:
    SYSLOGD="-u syslog"
    The new line will read:
    SYSLOGD="-a /home/chroot/dev/log -u syslog"
    You will need to tell sysklogd to restart to get the new config; use the following command:
    sudo /etc/init.d/sysklogd restart
    From what I read online, some programs may need /etc/passwd in order to run properly (I think scp). To play it safe, place a copy of /etc/passwd in the chroot directory using the following command:
    sudo cp /etc/passwd /home/chroot/etc/
    For security reasons, you will probably want to remove all irrelevant lines from the passwd file in "/home/chroot/etc/". So for my passwd file, since the name of the account that will use this chrooted directory, I only have the line:
    sft:x:1001:1001:Secure File Transfer Account,,,:/home/sft:/usr/bin/rssh
    WARNING: Please edit only the chroot copy of the passwd file, not the real one in /etc/passwd.
    You can use nano or another text editor to remove the other lines. (I also changed the home directory in the chroot passwd file from "/home/chroot/home/sft" to "/home/sft". I'm not sure if this is necessary, but I did this because I felt this will be better.)

    In order for the chrooting process to work, "/usr/lib/rssh/rssh_chroot_helper" has to be setuid root. (Note: this path is relative to real root, not chroot root.) To setuid root, run the command:
    sudo chmod u+s /usr/lib/rssh/rssh_chroot_helper

    Now remember how rssh thinks that the sftp subsystem is located at "/usr/lib/sftp-server" but it is actually located in "/usr/lib/openssh/sftp-server"? If not, you can run the command:
    rssh -v
    to figure it out. (Note: if this is not the case on your system, since our configs may differ, you should not follow this step and you should not follow one of the previous steps where you changed sftp_server_path="/usr/lib/sftp-server" to sftp_server_path="/usr/lib/openssh/sftp-server".)

    If however, your sftp-server is located in "/usr/lib/openssh/" and rssh thinks that it is located in "/usr/lib/" and your sshd (ssh server) thinks that the sftp subsystem is located at "/usr/lib/openssh/", make the following changes. (Note: you can check where sshd thinks the sftp subsystem is by the following command:
    cat /etc/ssh/sshd_config | grep "Subsystem sftp "
    First, create a link to "/usr/lib/openssh/sftp-server" at "/usr/lib/". (Note: I already found a symbolic link to sftp-server in my "/usr/lib", so I kept it as a symbolic link. However, a hard link seems more reasonable to me. I'll let you decide which one you want. If you don't know the difference between a symbolic link and a hard link, feel free to look it up; if you know how to explain the difference properly, please post an explanation.)

    To create the symbolic link, use the command:
    sudo ln -s /usr/lib/openssh/sftp-server /usr/lib/
    To create the hard link, use the command:
    sudo ln /usr/lib/openssh/sftp-server /usr/lib/
    Now that the sftp-server exists in "/usr/lib", you can change the config file for your sshd. Use your text editor to edit "/etc/ssh/sshd_config". For me, the command was:
    sudo nano /etc/ssh/sshd_config
    Then find the line:
    Subsystem sftp /usr/lib/openssh/sftp-server
    and replace it with:
    Subsystem sftp /usr/lib/sftp-server
    Save and exit the text editor when done. In order for the new config to take effect, you need to tell sshd to reload the config using the following command:
    sudo /etc/init.d/ssh reload
    Now you have to fix your chroot directory setup (you need to be able to run "/usr/lib/sftp-server" even when chrooted). To do this, create a hard link between for "/home/chroot/usr/lib/openssh/sftp-server" at "/home/chroot/usr/lib/" using the following command:
    sudo ln /home/chroot/usr/lib/openssh/sftp-server /home/chroot/usr/lib/
    Finally, there may be some files in the rsshed account's home directory like ".bashrc". If these are not needed, you can just delete them using the command "rm".

    At this point, your setup should be done (unless you or I missed a step).

    Fire up your favorite SFTP client and test the new setup. Hopefully it will work. Now try to ssh in using the rsshed account. A message should appear, and then rssh should exit, closing the connection.

    If you get a "connection closed" error and you have followed all the steps, adding null to your chrooted dev directory may help. You can do this with the command
    mknod -m 666 /home/chroot/dev/null c 1 3
    where /home/chroot is the chroot directory.

    Side note: If the user with the chrooted rsshed account manages to get to the server & get to the graphical login, they can login like a normal user (without chroot restrictions & without protection provided by rssh since the rssh shell is not the login shell).

    I have discovered that this setup will still allow people to use the port forwarding feature of SSH if it is enabled on the server. See the blue section below for the fix.
    Update on AllowTcpForwarding:
    You can use "Match" in your sshd_config to allow/disallow certain groups/users the ability to forward TCP connections. Thanks to oojah for this information. (He placed the rssh users into a group called "chroot" in this example.)
    Last edited by jchau; December 27th, 2009 at 02:37 AM. Reason: To note that rssh is no longer necessary to provided chrooted SFTP access.


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts