# SFTP chroot

From ArchWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Related articles

- SSHFS

OpenSSH 4.9+ includes a built-in chroot for SFTP, but requires a few tweaks to the normal install.

## Installation

Install and configure OpenSSH. Once running, make sure `sftp-server` has been set correctly:

    /etc/ssh/sshd_config

    Subsystem sftp /usr/lib/ssh/sftp-server

Access files with sftp or SSHFS. Many standard FTP clients should work as well.

## Configuration

### Setup the filesystem

Note:

- Readers may select a file access scheme on their own. For example, optionally create a subdirectory for an incoming (writable) space and/or a read-only space. This need not be done directly under `/srv/ssh/jail` - it can be accomplished on the live partition which will be mounted via a bind mount as well.
- It is also possible chrooting into `/home` directory thus skipping the usage of bind, however the desired user home directory should be owned by root:

    # chown root:root /home/<username>
    # chmod 0755 /home/<username>

Bind mount the live filesystem to be shared to this directory. In this example, `/mnt/data/share` is to be used, owned by user `root` and has octal permissions of `755`:

    # chown root:root /mnt/data/share
    # chmod 755 /mnt/data/share
    # mkdir -p /srv/ssh/jail
    # mount -o bind /mnt/data/share /srv/ssh/jail

Add entries to fstab to make the bind mount survive on a reboot:

    /mnt/data/share /srv/ssh/jail  none   bind   0   0

### Create an unprivileged user

Note: You do not need to create a group, it is possible to use `Match User` instead of `Match Group`.

Create the `sftponly` user group:

    # groupadd sftponly

Create a user that uses sftponly as main group and has shell login access denied:

    # useradd -g sftponly -s /usr/bin/nologin -d /srv/ssh/jail username

Set a (complex) password to prevent `account is locked` error (may appear even with key authentication):

    # passwd username

### Configure OpenSSH

Note: You may want to use `Match User` instead of `Match Group` as been given in the previous step.

    /etc/ssh/sshd_config

    Subsystem sftp /usr/lib/ssh/sftp-server

    Match Group sftponly
      ChrootDirectory %h
      ForceCommand internal-sftp
      AllowTcpForwarding no
      X11Forwarding no
      PasswordAuthentication no

Restart `sshd.service` to confirm the changes.

#### Fixing path for authorized_keys

Tip: Use the debug mode of OpenSSH on the client and server in case of `(pre)auth` error(s).

With the standard path of AuthorizedKeysFile, the SSH keys authentication will fail for chrooted-users. To fix this, append a root-owned directory on AuthorizedKeysFile to `/etc/openssh/sshd_config` e.g. `/etc/ssh/authorized_keys`, as example:

    /etc/ssh/sshd_config

    AuthorizedKeysFile /etc/ssh/authorized_keys/%u .ssh/authorized_keys
    PermitRootLogin no
    PasswordAuthentication no
    PermitEmptyPasswords no
    Subsystem sftp /usr/lib/ssh/sftp-server

Create authorized_keys folder, generate a SSH-key on the client, copy the contents of the key to `/etc/ssh/authorized_keys` (or any other preferred method) of the server and set correct permissions:

    # mkdir /etc/ssh/authorized_keys
    # chown root:root /etc/ssh/authorized_keys
    # chmod 755 /etc/ssh/authorized_keys
    # echo 'ssh-rsa <key> <username@host>' >> /etc/ssh/authorized_keys/username
    # chmod 644 /etc/ssh/authorized_keys/username

Restart `sshd.service`.

## Tips and tricks

### Write permissions

The bind path needs to be fully owned by `root`, however files and/or subdirectories do not have to be. In the following example the user www-demo uses `/srv/ssh/www/demo` as the jail-directory:

    # mkdir /srv/ssh/www/demo/public_html
    # chown www-demo:sftponly /srv/ssh/www/demo/public_html
    # chmod 755 /srv/ssh/www/demo/public_html

The user should now be able to create files/subdirectories inside this directory. See File permissions and attributes for more information.

### Logging

The user will not be able to access `/dev/log`. This can be seen by running `strace` on the process once the user connects and attempts to download a file.

#### Create sub directory

Create the sub-directory `dev` in the `ChrootDirectory`, for example:

    # mkdir /usr/local/chroot/user/dev
    # chmod 755 /usr/local/chroot/user/dev

Now you should create socket at `/usr/local/chroot/user/dev/log` which will be used by openssh. You may directly bind this socket to `/dev/log` (or `/run/systemd/journal/dev-log` in case you are using journald) or create using `syslog-ng`/`rsyslog`.

#### Bind to journald

    # touch /usr/local/chroot/user/dev/log
    # mount --bind /run/systemd/journal/dev-log /usr/local/chroot/user/dev/log

#### Syslog-ng configuration

Add to `/etc/syslog-ng/syslog-ng.conf` a new source for the log and add the configuration, for example change the section:

    source src {
      unix-dgram("/dev/log");
      internal();
      file("/proc/kmsg");
    };

to:

    source src {
      unix-dgram("/dev/log");
      internal();
      file("/proc/kmsg");
      unix-dgram("/usr/local/chroot/theuser/dev/log");
    };

and append:

    #sftp configuration
    destination sftp { file("/var/log/sftp.log"); };
    filter f_sftp { program("internal-sftp"); };
    log { source(src); filter(f_sftp); destination(sftp); };

(Optional) If you would like to similarly log SSH messages to its own file:

    #sshd configuration
    destination ssh { file("/var/log/ssh.log"); };
    filter f_ssh { program("sshd"); };
    log { source(src); filter(f_ssh); destination(ssh); };

(From Syslog-ng#Move log to another file)

#### OpenSSH configuration

Edit `/etc/ssh/sshd_config` to replace all instances of `internal-sftp` with `internal-sftp -f AUTH -l VERBOSE`

#### Restart service

Restart service `syslog-ng` and `sshd`.

`/usr/local/chroot/theuser/dev/log` should now exist.

## Alternatives to SFTP

### Secure copy protocol (SCP)

Installing openssh provides the scp command to transfer files. SCP may be faster than using SFTP [1].

Install rsshAUR or scponly as alternative shell solutions.

#### Scponly

install scponly.

For existing users, simply set the user's shell to scponly:

    # usermod -s /usr/bin/scponly username

See the Scponly Wiki for more details.

#### Adding a chroot jail

The package comes with a script to create a chroot. To use it, run:

    # /usr/share/doc/scponly/setup_chroot.sh

- Provide answers
- Check that `/path/to/chroot` has `root:root` owner and `r-x` for others
- Change the shell for selected user to `/usr/bin/scponlyc`
- sftp-server may require some libnss modules such as libnss_files. Copy them to chroot's `/lib` path.

## See also

- https://www.minstrel.org.uk/papers/sftp/builtin/
- sshd_config(5)

Categories:

- File Transfer Protocol
- Secure Shell