Назад | Перейти на главную страницу

SFTP с chroot в зависимости от открытого ключа подключающегося пользователя

Я хочу создать сервер (под управлением Debian или FreeBSD), который будет получать резервные копии от разных клиентов через sshfs. Каждый клиент должен иметь возможность читать и записывать собственные данные резервного копирования, но не данные других клиентов.

У меня была такая идея: каждый клиент подключается через auth с открытым ключом к backup@backupserver.local. Пользователь резервное копирование имеет специальный файл authorized_keys, например:

command="internal-sftp" chroot="/backup/client-1/data" ssh-rsa (key1)
command="internal-sftp" chroot="/backup/client-2/data" ssh-rsa (key2)
command="internal-sftp" chroot="/backup/client-3/data" ssh-rsa (key3)
etc...

Преимущество этого заключается в том, что мне не нужно использовать отдельного пользователя для каждого клиента, и я могу легко автоматически сгенерировать файл authorized_keys с помощью сценария.

Есть только одна проблема: chroot=... не работает. Файл authorized_keys OpenSSH, похоже, не имеет эквивалента для ChrootDirectory (который работает в / etc / ssh / sshd_config, либо глобально, либо в блоке Match User).

Есть ли достаточно простой способ выполнить то, что я хочу, используя OpenSSH? Может быть, используя command=... директива умным способом? В качестве альтернативы, есть ли другие серверы SFTP, которые могут делать то, что я хочу?

РЕДАКТИРОВАТЬ: Чтобы прояснить, чего я хочу достичь: я хочу, чтобы несколько клиентов могли хранить файлы на моем сервере. Каждый клиент не должен видеть файлы других клиентов. И я не хочу засорять свой сервер десятками учетных записей пользователей, поэтому я хотел бы легко управляемое решение, чтобы клиенты могли совместно использовать учетную запись пользователя и при этом не иметь доступа к файлам друг друга.

в chroot=... не работает.

Нет, на странице руководства для sshd, описывающий формат authorized_keys файл.

Если бы вы поместили chroot в command=, вы не сможете использовать internal-sftp, потому что это подстановка внутреннего вызова функции внутри sshd.

Рекомендуемый способ - настроить больше пользователей, если вам нужно разделение. Вы также можете использовать аргументы для internal-sftp, если вам не нужно строгое разделение (например, только разные рабочие каталоги), например

command="internal-sftp -d /backup/client-1/data" ssh-rsa (key1)

Также можно ограничить количество запросов, используя -P вариант, как на странице руководства для sftp-server.

В качестве альтернативы, есть ли другие серверы SFTP, которые могут делать то, что я хочу?

да, вы можете использовать proftpd

Подготовить пользовательскую среду. С ProFTPD нет необходимости предоставлять пользователю действующую оболочку.

# useradd -m -d /vhosts/backup/user1/ -s /sbin/nologin user1
# passwd --lock user1
Locking password for user user1.
passwd: Success

# mkdir /vhosts/backup/user1/.sftp/
# touch /vhosts/backup/user1/.sftp/authorized_keys

# chown -R user1:user1 /vhosts/backup/user1/
# chmod -R 700 /vhosts/backup/user1/

Чтобы использовать открытые ключи OpenSSH в SFTPAuthorizedUserKeys, вы должны преобразовать их в формат RFC4716. Вы можете сделать это с помощью инструмента ssh-keygen:

# ssh-keygen -e -f user1.public.key > /vhosts/backup/user1/.sftp/authorized_keys

Настроить ProFTPD

ServerName "ProFTPD Default Installation"
ServerType standalone
DefaultServer off

LoadModule mod_tls.c
LoadModule mod_sftp.c
LoadModule mod_rewrite.c

TLSProtocol TLSv1 TLSv1.1 TLSv1.2

# Disable default ftp server
Port 0

UseReverseDNS off
IdentLookups off

# Umask 022 is a good standard umask to prevent new dirs and files
# from being group and world writable.
Umask 022

# PersistentPasswd causes problems with NIS/LDAP.
PersistentPasswd off

MaxInstances 30

# Set the user and group under which the server will run.
User nobody
Group nobody

# Normally, we want files to be overwriteable.
AllowOverwrite                  on

TimesGMT off
SetEnv TZ :/etc/localtime

<VirtualHost sftp.example.net>
    ServerName "SFTP: Backup server."
    DefaultRoot ~
    Umask 002
    Port 2121

    RootRevoke on

    SFTPEngine on
    SFTPLog /var/log/proftpd/sftp.log

    SFTPHostKey /etc/ssh/ssh_host_rsa_key
    SFTPHostKey /etc/ssh/ssh_host_dsa_key
    SFTPDHParamFile /etc/pki/proftpd/dhparam_2048.pem
    SFTPAuthorizedUserKeys file:~/.sftp/authorized_keys

    SFTPCompression delayed
    SFTPAuthMethods publickey
</VirtualHost>

<Global>
    RequireValidShell off
    AllowOverwrite yes

    DenyFilter \*.*/

    <Limit SITE_CHMOD>
        DenyAll
    </Limit>
</Global>

LogFormat default "%h %l %u %t \"%r\" %s %b"
LogFormat auth    "%v [%P] %h %t \"%r\" %s"
ExtendedLog /var/log/proftpd/access.log read,write

Создайте параметры группы DH (Diffie-Hellman).

# openssl dhparam -out /etc/pki/proftpd/dhparam_2048.pem 2048

Настройте любой SFTP-клиент. Я использовал FileZilla

Если вы запускаете ProFPTD в режиме отладки

# proftpd -n -d 3 

В консоли вы увидите что-то вроде следующего

2016-02-21 22:12:48,275 sftp.example.net proftpd[50511]: using PCRE 7.8 2008-09-05
2016-02-21 22:12:48,279 sftp.example.net proftpd[50511]: mod_sftp/0.9.9: using OpenSSL 1.0.1e-fips 11 Feb 2013
2016-02-21 22:12:48,462 sftp.example.net proftpd[50511] sftp.example.net: set core resource limits for daemon
2016-02-21 22:12:48,462 sftp.example.net proftpd[50511] sftp.example.net: ProFTPD 1.3.5a (maint) (built Sun Feb 21 2016 21:22:00 UTC) standalone mode STARTUP
2016-02-21 22:12:59,780 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): mod_cap/1.1: adding CAP_SETUID and CAP_SETGID capabilities
2016-02-21 22:12:59,780 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): SSH2 session opened.
2016-02-21 22:12:59,863 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): Preparing to chroot to directory '/vhosts/backup/user1'
2016-02-21 22:12:59,863 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): Environment successfully chroot()ed
2016-02-21 22:12:59,863 sftp.example.net proftpd[50512] sftp.example.net (192.168.1.2[192.168.1.2]): USER user1: Login successful

И следующие строки в /var/log/sftp.log

2016-02-21 22:12:48,735 mod_sftp/0.9.9[50309]: sending acceptable userauth methods: publickey
2016-02-21 22:12:48,735 mod_sftp/0.9.9[50309]: public key MD5 fingerprint: c2:2f:a3:93:59:5d:e4:38:99:4b:fd:b1:6e:fc:54:6c
2016-02-21 22:12:48,735 mod_sftp/0.9.9[50309]: sending publickey OK
2016-02-21 22:12:59,789 mod_sftp/0.9.9[50309]: public key MD5 fingerprint: c2:2f:a3:93:59:5d:e4:38:99:4b:fd:b1:6e:fc:54:6c
2016-02-21 22:12:59,790 mod_sftp/0.9.9[50309]: sending userauth success
2016-02-21 22:12:59,790 mod_sftp/0.9.9[50309]: user 'user1' authenticated via 'publickey' method

P.S.

Настроенный путь к файлу, содержащему авторизованные ключи (SFTPAuthorizedUserKeys) можно использовать % u переменная, которая будет интерполирована с именем аутентифицируемого пользователя. Эта функция поддерживает наличие файлов авторизованных ключей для каждого пользователя, которые находятся в центральном месте, вместо того, чтобы требовать (или позволять) пользователям управлять своими собственными авторизованными ключами. Например:

SFTPAuthorizedUserKeys file:/etc/sftp/authorized_keys/%u

Я хочу, чтобы несколько клиентов могли хранить файлы на моем сервере. Каждый клиент не должен видеть файлы других клиентов. И я не хочу засорять свой сервер десятками учетных записей пользователей, поэтому я хотел бы легко управляемое решение, чтобы клиенты могли совместно использовать учетную запись пользователя и при этом не иметь доступа к файлам друг друга.

с ProFTPD это тоже возможно. Вам просто нужно немного изменить мою первоначальную конфигурацию

<VirtualHost sftp.example.net>
    ...   
    SFTPAuthorizedUserKeys file:/etc/proftpd/sftp_authorized_keys
    AuthUserFile /etc/proftpd/sftp_users.passwd

    CreateHome on 0700 dirmode 0700 uid 99 gid 99

    RewriteHome on
    RewriteEngine on
    RewriteLog /var/log/proftpd/rewrite.log
    RewriteCondition %m REWRITE_HOME
    RewriteRule (.*) /vhosts/backup/%u
</VirtualHost>

И создайте одну виртуальную учетную запись

# ftpasswd --passwd --file /etc/proftpd/sftp_users.passwd --sha512 --gid 99 --uid 99 --shell /sbin/nologin --name user1 --home /vhosts/backup

Вот и все. Для каждой дополнительной учетной записи все, что вам нужно, это добавить его открытый ключ в файл / etc / proftpd / sftp_authorized_keys

Примечание: файл в конце должен содержать новую строку! Это важно.

Тем временем я придумал еще одно простое решение, которое тоже отлично работает, по крайней мере, в моем случае использования:

Каждый клиент подключается к серверу с одной и той же учетной записью и, возможно, даже с одним и тем же ключом (не имеет значения). OpenSSH перемещается в каталог со следующей структурой:

d--x--x---   dark-folder
drwxr-x---   |- verylongrandomfoldername1
drwxr-x---   |- verylongrandomfoldername2
drwxr-x---   `- ...

Вместе с командой резервного копирования сервер сообщает клиенту имя папки, в которую он должен поместить свои файлы. Имена папок представляют собой 64-байтовые случайные строки, которые практически невозможно угадать, поэтому каждый клиент может действительно получить доступ только к своей собственной папке, даже если другие находятся «где-то там в темноте».

режим d - x - x-- в темной папке гарантирует, что каждый клиент может войти в папку (и папки ниже), но не может перечислить ее содержимое или создать какие-либо новые записи.

Подпапки создаются процессом сервера резервного копирования, а соединение между клиентом и папкой сохраняется (среди прочего) в sqlite db.