带有chroot的SFTP取决于连接用户的公钥


9

我想构建一个服务器(运行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=...不能正常工作。OpenSSH的authorized_keys文件似乎没有与ChrootDirectory等效的文件(可在/ etc / ssh / sshd_config中全局或在“匹配用户”块中使用)。

有没有使用OpenSSH完成我想要的工作的合理简单方法?也许command=...以一种聪明的方式使用指令?另外,还有其他SFTP服务器可以执行我想要的操作吗?

编辑:为了更清楚我要实现的目的:我希望多个客户端能够在我的服务器上存储文件。每个客户端都不能看到其他任何客户端的文件。而且我不想在服务器上堆满几十个用户帐户,因此我想为客户提供一个易于管理的解决方案,使客户端共享一个用户帐户,但仍然无法访问彼此的文件。

Answers:


5

另外,还有其他SFTP服务器可以执行我想要的操作吗?

是的,您可以使用proftpd

准备用户环境。使用ProFTPD,无需为用户提供有效的shell。

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

为了在SFTPAuthorizedUserKeys中使用OpenSSH公钥,必须将它们转换为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

FileZilla SFTP服务器设置

如果以调试模式运行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

聚苯乙烯

包含授权密钥(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中

注意:文件末尾必须包含换行!这一点很重要。


感谢您的详细回答。但是,我看不出这将如何帮助我实现我的主要目标,即对许多不应该查看彼此文件的客户端仅使用一个用户帐户。(并且可以通过脚本轻松管理。)再次阅读我的原始问题,我承认我想要实现的目标可能并不完全清楚。抱歉
Xykon42 '16

我已经更新了答案
ALex_hha '16

1
好的,只需稍作更改,实际上效果很好,谢谢!为了确保用户无法通过猜测其他用户的文件名来访问其他文件(或通过滥用CreateHome函数来淹没我的服务器),authorized_keys文件必须是特定于用户的,例如/foo/authorized_keys.d/%u。
Xykon42 '16

6

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


0

同时,我想出了另一个简单的解决方案,该解决方案至少在我的用例中也能正常工作:

每个客户端都使用相同的用户帐户甚至可能是相同的密钥连接到服务器(无关紧要)。OpenSSH chroots进入具有以下结构的目录:

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

服务器与备份命令一起,告诉客户端应将其文件放入其中的文件夹名称。文件夹名称是64字节的随机字符串,几乎无法猜测,因此每个客户端只能真正访问自己的文件夹,即使其他客户端“在黑暗中”。

深色文件夹上的d--x--x--模式可确保每个客户端都可以进入该文件夹(和下面的文件夹),但不能列出其内容或创建任何新条目。

子文件夹由备份服务器进程创建,并且客户端和文件夹之间的连接(除其他外)存储在sqlite db中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.