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

我想build立一个服务器(运行Debian或FreeBSD),通过sshfs从不同的客户端接收备份。 每个客户端应该能够读取和写入自己的备份数据,但不能读取任何其他客户端的数据。

我有以下想法:每个客户端通过公钥validation连接到[email protected]。 用户备份有一个特殊的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服务器可以做我想要的吗?

编辑 :为了更清楚我想实现什么:我想要几个客户端能够存储在我的服务器上的文件。 每个客户端都不应该能够看到其他客户端的文件。 而且我不想用几十个用户帐户来清理我的服务器,所以我想要一个易于pipe理的解决scheme,让客户共享一个用户帐户,并且仍然无法访问彼此的文件。

另外,还有其他的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 

创buildDH(Diffie-Hellman)组参数。

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

configuration任何SFTP客户端。 我用过FileZilla

FileZilla SFTP服务器设置

如果在debugging模式下运行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 

PS

包含授权密钥( SFTPAuthorizedUserKeys )的文件的configurationpath可以使用%uvariables,该variables将被插入到被authentication用户的名称中。 此function支持将位于中央位置的授权密钥的每个用户文件,而不是要求(或允许)用户pipe理自己的授权密钥。 例如:

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

我想要几个客户端能够将文件存储在我的服务器上。 每个客户端都不应该能够看到其他客户端的文件。 而且我不想用几十个用户帐户来清理我的服务器,所以我想要一个易于pipe理的解决scheme,让客户共享一个用户帐户,并且仍然无法访问彼此的文件。

与ProFTPD也是可能的。 你只需要一点点修改我的初始configuration

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

并创build一个虚拟帐户

 # 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

注意:该文件最后必须包含新行! 这一点很重要。

chroot=...不起作用。

不,在sshd的手册页中没有这样的描述authorized_keys文件的格式。

如果你将chroot放入command= ,你将无法使用internal-sftp ,因为它是sshd内部函数调用的替代。

推荐的方式是build立更多的用户,如果你需要分离。 如果你不需要严格的分离(例如只是不同的工作目录),你也可以使用internal-sftp参数,比如

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

也可以使用-P选项限制请求数量,如sftp-server手册页中所示。

与此同时,我想出了另一个简单的解决scheme,至less在我的使用情况下也能正常工作:

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

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

与备份命令一起,服务器通知客户端文件夹名称,它应该把文件放入。 文件夹名称是64字节的随机string,实际上是不可猜测的,所以每个客户端只能真正访问自己的文件夹,即使其他文件夹“在黑暗中的某个地方”。

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

子文件夹是由备份服务器进程创build的,客户端和文件夹之间的连接存储(除别的以外)在sqlite数据库。