SSH с chroot и работающими только «sftp», «rsync» (оба)?

SSH с chroot и работающими только «sftp», «rsync» (оба)?

У меня на сервере Ubuntu есть два пользователя и одна общая папка:

  1. Пользователь writer, имеющий доступ на запись в /var/shared. Это приложение регулярно вносит изменения в файлы в этой папке удаленно с помощью ключа SSH.

  2. Пользователь readerиспользуется несколькими клиентами с ключом SSH, который они могут получить без моего разрешения, поэтому мне нужно ограничить команды, доступные в этой оболочке.

Вопрос:

Мне нужно ограничить команды, доступные пользователю, readerчтобы он мог использовать только протоколы sftp и rsync (без стандартных команд типа mkdir, ls, top, ...). Только каталог /var/sharedдолжен быть доступен для чтения и должен быть корневым путем, например, не нужно cdв него входить, он уже есть /в sftp или rsync.

Как написать скрипт оболочки, чтобы я мог применить его к usermod -sпользователю reader, который будет вести себя таким образом?Я не могу найти никаких образцов. Как мне сделать так, чтобы writerтакже оставалось "заключенным" в /var/share, чтобы пути были такими же?

Примечания:

  1. Я уже пробовал директивы sshd_config's Match, ForceCommand internal-sftpи ChrootDirectory. Это требует, ChrootDirectoryчтобы владел root и был недоступен для записи (755 или меньше), и не поддерживает rsync.

  2. Я пробовал rssh, но это просто не работает для каталогов за пределами домашнего каталога вошедшего в систему пользователя. Поэтому я не мог chroot пользователей в тот же каталог с разными разрешениями.

  3. Я пытался использовать command=".." ssh-rsa....в authorized_keysфайле, но не понял, как включить нужное мне поведение, я только проверяю rrsyncскрипт из документации rsync. Этот метод не имеет chrootнужной мне функции.

Можно ли хотя бы пример для таких оболочек? Возможно ли это сделать скриптами?

Bash и C++ (при необходимости) приветствуются. Вывод 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)

решение1

Прежде всего, ChrootDirectoryон должен принадлежать пользователю root и не быть доступным для записи другим пользователям. Таким образом, /var/sharedв вашем случае не может быть ChrootDirectoryзначением.

Я бы рекомендовал создать каталог, доступный для записи только пользователю root, и сделать /var/sharedсодержимое этого каталога доступным либо через монтирование Linux, либо с помощью каких-либо обходных путей с использованием символических ссылок.

Если вам нужно ограничить sftpили rsync, вам нужно проверить SSH_ORIGINAL_COMMANDпеременную окружения на сервере с помощью "обертки", принудительно применяемой либо через ForceCommand, либо через commandв открытом ключе ssh, эта переменная заполняется после аутентификации пользователя и содержит информацию о том, какой тип соединения собираются установить клиенты. Для sftpнего будет иметь sftp-serverвнутри, для rsyncнего будет иметь rsync, для просто sshсеанса он будет иметь, IIRC, переменная пустая, для ssh dateнего будет date. SSH_ORIGINAL_COMMANDзапускается под аутентифицированным пользователем на сервере!

Это может быть началом вашей обертки:

#!/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

Как вы можете видеть, ssh -vдает вам информацию о том, какая команда будет выполнена сервером. Таким образом, вы можете изменить /tmpна что-то другое в вашей обертке.

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

Связанный контент