Results 1 to 10 of 12

Thread: HOWTO: Install and setup chrooted SFTP users with openssh-5.0p1 from scratch

Threaded View

  1. #1
    Join Date
    Jul 2008
    Columbus, Ohio, USA
    Kubuntu 8.04 Hardy Heron

    HOWTO: Install and setup chrooted SFTP users with openssh-5.0p1 from scratch

    I've been wanting to set up an encrypted FTP server for a while (sftp) in a chroot'ed environment, so I did a few hours of half-baked-blog parsing and keyboard-pounding in order to figure this out in a way that would work consistently, even if it isn't 100% efficient (your noob-dar should be flashing right about now ). Since version 4.8, openssh has had the ability to (fairly) easily chroot sftp users into a specified directory using a new sshd_config directive, ChrootDirectory. The purpose of this guide is to demonstrate how to set up a simple chrooted sftp system from square one implementing this self-contained chroot mechanism (using only openssh without the need for rssh), and how to add users under this paradigm.

    This guide was tested from start to finish on a fresh install of Kubuntu 8.04.1 on a Dell Inspiron 1501.

    The only version tested under this guide is openssh-5.0p1.

    (1) Package Installation

    In case you already have openssh (the older repo version) installed, you'll want to get rid of it.

    BE WARNED: the following command should not only uninstall ssh but will also purge your system of any associated configuration files, so make sure they're backed up if you think you might need them later.

    $ sudo apt-get purge ssh openssh-*
    Reboot and make sure your ssh server isn't running (it shouldn't be, it's gone!):

    $ ps ax | grep ssh # shouldn't show openssh-server
    It's ok if 'grep ssh' is returned. There might still be a startup script in /etc/init.d which you may want to get rid of (again, back it up if you think you'll need it later):

    $ sudo rm /etc/init.d/ssh
    {Ku,Xu,U}buntu doesn't come with the libraries needed to build openssh from source, so you'll need to instruct apt to install everything else necessary to compile an end-package from scratch (in this case, the package is openssh-server) using the following command:

    $ sudo apt-get build-dep openssh-server
    There's a "privilege separation" method in openssh which shuffles root-level operations off to a privileged monitor process (stolen shamelessly from the README file). Set it up as follows (ignoring any 'File exists' messages):

    $ sudo mkdir /var/empty
    $ sudo chown root:sys /var/empty
    $ sudo chmod 755 /var/empty
    $ sudo groupadd sshd
    $ sudo useradd -g sshd -c 'sshd privsep' -d /var/empty -s /bin/false sshd
    Next, you're going to need the actual openssh source package. You can retrieve it from one of a slew of mirrors here, or wget it per the example below. Once downloaded (you did download openssh-5.0p1.tar.gz, right?), the preparation/build process is simple as usual:

    $ wget # optional (don't bother if you've downloaded it elsewhere)
    $ tar xvf openssh-5.0p1.tar.gz
    $ cd openssh-5.0p1/
    $ ./configure
    $ make
    $ sudo make install
    Now we're going to make a quick change to the sftp handler. Installing from source puts your main config file (sshd_config) in /usr/local/etc/ by default; open sshd_config there with your favorite text editor (I use emacs).

    $ sudo emacs /usr/local/etc/sshd_config
    Find the line that starts with the word "Subsystem". It should appear in a block that looks something like this:

    # override default of no subsystems
    Subsystem sftp /usr/local/libexec/sftp-server
    Comment it out like so:

    # override default of no subsystems
    # Subsystem sftp /usr/local/libexec/sftp-server
    Just beneath it, add this line:

    Subsystem sftp internal-sftp
    This causes openssh's sftp server to run in a mode which allows you to chroot someone without having to copy over shells, libraries, etc.
    Save and exit your editor.

    If you'd like this to start when your computer boots, go edit /etc/rc.local using your favorite text editor.

    $ sudo emacs /etc/rc.local
    There should be a line at the end that says "exit 0". Just above this line, add the following:

    Save and exit your editor. We're now ready to add users.


    (2) User Setup

    This section should be repeated for each user to whom you grant sftp-only access.

    Because sftp (as included with openssh) wraps around ssh, your users are going to need system accounts. Let's prepare a user named johndoe (replace johndoe with whatever new user account you wish). The user johndoe should, in this case, only be able to log in using sftp (as opposed to ssh) once we're done.

    $ sudo mkdir /home/johndoe
    $ sudo useradd johndoe
    We'll have to set their home directory permissions appropriately. It's important that root owns this and that its group ID is identical to the username, and that the permissions are set so that only root can write:

    $ sudo chown root:johndoe /home/johndoe
    $ sudo chmod 755 /home/johndoe
    Force the normal login directory just in case:

    $ sudo usermod -d /home/johndoe johndoe
    Now give him a password:

    $ sudo passwd johndoe
    (2a) Public/Private Key Authentication (optional)

    Public/private key pairs allow you to log in using signing "certificates" indicating that an entity (in this case, the sftp client-side computer) is implicitly trusted ("friendly"). Configuring OpenSSH to use these allows you, in short, to log in without requiring a password, or using a password of the client's choice. Let's get down to business, then:

    On the client-side (i.e., the computer you will be using to access the sftp server), you'll need to generate a public/private key pair. Let us herein refer to the client-side as "johndoe's computer" (johndoes-computer) so there's no question which one we're talking about vs. your server device (sftp-host).

    For the moment let's change the owner of the sftp user's home directory so that they can write to it remotely.

    [sftp-host]$ sudo chown johndoe:johndoe /home/johndoe
    Unless you are sitting in front of johndoe's computer (in which case this command is redundant), ssh into it (assuming openssh-server is installed on it, either from the repos or via step (1)):

    [sftp-host]$ ssh someuser@johndoes-ip
    Now we generate our key pair. Generally speaking 1024 bits is an adequate key length, but you can modify the size (powers of 2 between 1024 and 32768 ) and type (dsa or rsa) at your discretion:

    [johndoes-computer]$ mkdir -p ~/.ssh
    [johndoes-computer]$ chmod 700 ~/.ssh
    [johndoes-computer]$ cd ~/.ssh
    [johndoes-computer]$ ssh-keygen -b 1024 -t rsa
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/someuser/.ssh/id_rsa): # Leave blank
    Enter passphrase (empty for no passphrase): # leave blank if you want to login without a password
    Enter same passphrase again: # leave this blank also if you want to login without a password
    Your identification has been saved in /home/someuser/.ssh/id_rsa.
    Your public key has been saved in /home/someuser/.ssh/
    The key fingerprint is:
    01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef someuser@johndoes-computer # Something similar to this
    Keep in mind that if you do set a passphrase for your RSH key, that will be your login password. Otherwise you will log in to sftp automatically without requiring one.

    (Note: One and only one keypair must be generated per user on johndoes-computer who wishes to log into the remote sftp server via pub/priv key authentication. However, various johndoes-computer users' public keys must be copied over for each sftp account said users hold on the remote server (as described in a moment).)

    This generates two files, "id_rsa" and "". "id_rsa" is your private key (which is not to leave johndoe's computer) and "" is your public key which must be securely copied to the sftp host, into (IMPORTANT!) johndoe's user (sftp) account home directory.

    [johndoes-computer]$ scp
    We're now done working on johndoe's computer, and return to the sftp host to add the key to an authorized list and set permissions appropriately, then change the owner of the folder back to root.

    [sftp-host]$ sudo mkdir -p /home/johndoe/.ssh
    [sftp-host]$ sudo chown johndoe:johndoe /home/johndoe/.ssh
    [sftp-host]$ sudo chmod 707 /home/johndoe/.ssh # so we can cat into that folder, might have permission problems otherwise
    [sftp-host]$ sudo cat /home/johndoe/ >> /home/johndoe/.ssh/authorized_keys
    [sftp-host]$ sudo chmod 700 /home/johndoe/.ssh
    [sftp-host]$ sudo chmod 600 /home/johndoe/.ssh/authorized_keys
    [sftp-host]$ sudo chown johndoe:johndoe /home/johndoe/.ssh/authorized_keys
    [sftp-host]$ sudo mv /home/johndoe/ /home/johndoe/.ssh/
    [sftp-host]$ sudo chown root:johndoe /home/johndoe
    Done! Continue below with user setup on the sftp host machine.


    (2) User Setup (continued)

    Set the new user a dummy shell (so they don't have real shell access).

    $ sudo usermod -s /bin/false johndoe
    Now we need to indicate that this particular user must be jailed into their home directory. We go back to edit /usr/local/etc/sshd_config ...

    $ sudo emacs /usr/local/etc/sshd_config
    ... and add the following at the very end of the file:

    Match User johndoe
          ChrootDirectory /home/johndoe
          ForceCommand internal-sftp
    As of now, user johndoe should have read access to his home directory. Let's give him a place to upload stuff:

    $ sudo mkdir /home/johndoe/upload
    $ sudo chown johndoe:johndoe /home/johndoe/upload
    $ sudo chmod 755 /home/johndoe/upload
    Done! You can stop here if you want.


    (3) Giving SFTP users read access to some other directory

    As an interesting aside, let's say you (the sysadmin) have a common info/media/data directory you wish to share with your sftp users without actually copying all that data over (or allowing it to be edited/deleted/corrupted). We can do this by mounting it read-only somewhere in their login directory. They're going to need a place to get to it:

    $ sudo mkdir /home/johndoe/readonly
    Now we mount our directory of choice (in this example, /home/sysadmin/junk/shared-data) as read-only in said folder:

    $ sudo mount -r --bind /home/sysadmin/junk/shared-data /home/johndoe/readonly
    It might help to add the above command to /etc/rc.local so that it happens automatically on startup. Anything added to rc.local will run as root at startup, so there is no need to indicate 'sudo'. In other words, you would add this command to /etc/rc.local as follows (before the 'exit 0' of course):

    mount -r --bind /home/sysadmin/junk/shared-data /home/johndoe/readonly
    Note: You cannot mount more than one folder/device/partition/netshare in a particular location. Doing so won't damage anything, but the mount point will only display the object mounted last in sequence.


    Reboot your computer. Now you should have the following:

    1) You are able to login using the command:

    $ sftp johndoe@sftp-host
    or using a client which supports sftp.

    2) You are unable to navigate above the indicated root directory (this means chroot worked!).

    3) You can read from directories, locally-mounted volumes, or files inside the chroot jail (as far as permissions allow).

    4) You can read-write within the designated "upload" directory.

    5) You cannot login johndoe using ssh.

    Hope that helps!
    Last edited by lusixhan; July 22nd, 2008 at 02:14 AM. Reason: Added public/private key authentication


Posting Permissions

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