3

I have two users and one shared folder in my Ubuntu server:

  1. User writer, which has write access to /var/shared. It's an application regularly making file changes in this folder from remote, with SSH key.

  2. User reader is used by multiple clients with SSH key, a key they can get without my permission, that's why I need to restrict commands available in this shell.

Question:

I need to restrict commands accessible for reader user, so it can use only sftp and rsync protocols (no standard commands like mkdir, ls, top, ..); Only directory /var/shared must be readable, and must be a root path, e.g. no need to cd into it, it's already / in sftp or rsync.

How to write a shell script so I can apply it with usermod -s for user reader that will give such behavior? I cannot find any samples. How to make writer also remain "jailed" to /var/share, so paths are same?

Notes

  1. I have tried sshd_config's Match, ForceCommand internal-sftp and ChrootDirectory directives already. This requires ChrootDirectory to be owned by root and non-writable (755 or less), also does not support rsync

  2. I have tried rssh, but it simply don't work for directories outside home directory for logged in user. So I couldn't chroot users to same directory with different permissions...

  3. I tried to use command=".." ssh-rsa.... in authorized_keys file, but didn't get how can I enable behavior which I need, I only check rrsync script from rsync's docs. This method has no chroot feature I need.

Can I have a sample at least for such shells? Is this achievable with scripts?

Bash and C++(if needed) are welcome. Output of ldd /bin/bash:

    linux-vdso.so.1 =>  (0x00007fff7e9d1000)
    libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f79dfd8b000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f79dfb87000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f79df7bd000)
    /lib64/ld-linux-x86-64.so.2 (0x000055bd0767c000)
  • You are almost there. The 755 permissions are a must, if you want a secure chroot, regardless technology. Then if you skip force command, you should be able to copy required binaries with dependencies into the chroot (rsync, sftp). But much easier would be to allow only one (sftp preferably). – Jakuje Jun 22 '16 at 10:53
0

First of all ChrootDirectory must be owned by root and not writable by other users. Thus /var/shared in your case cannot be ChrootDirectory value.

I would recommend to create a directory which would be writable by root only and make /var/shared accessible inside this dir either via Linux bind-mounting or some kind of symlinks workarounds.

If you need restrict sftp or rsync, you need to check SSH_ORIGINAL_COMMAND environment variable on the server with help of a "wrapper" enforced either via ForceCommand or via command in ssh public key, this variable is populated after user is authenticated and contains info what kind of connection clients is going to establish. For sftp it would have sftp-server inside, for rsync it would have rsync, for just ssh session it would have, IIRC, the variable empty, for ssh date it would be date. SSH_ORIGINAL_COMMAND is run under authenticated user on the server!

This could be your start of the wrapper:

#!/usr/bin/env bash

set -eu
set -o pipefail

[[ -z "${SSH_ORIGINAL_COMMAND:-}" ]] && exit 1

case "${SSH_ORIGINAL_COMMAND}" in
    "/usr/libexec/openssh/sftp-server")
        exec /usr/libexec/openssh/sftp-server
        ;;
    "rsync --server"*)
        exec ${SSH_ORIGINAL_COMMAND}
        ;;
    *)
        exit 1
        ;;
esac

As you can see, ssh -v gives you info about what command would be executed by the server. Thus you can change /tmp to something else in your wrapper as well.

$ rsync -a -e "ssh -v" bin localhost:/tmp/ 2>&1 | grep '^debug.*Sending command:'
debug1: Sending command: rsync --server -logDtpre.iLsfxC . /tmp/

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.