Linux

SFTP 與 chroot 取決於連接使用者的公鑰

  • March 11, 2016

我想建構一個伺服器(執行 Debian 或 FreeBSD),通過 sshfs 接收來自不同客戶端的備份。每個客戶端都應該能夠讀取和寫入自己的備份數據,但不能讀取和寫入任何其他客戶端的數據。

我有以下想法:每個客戶端都通過公鑰認證連接到 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 中工作,無論是全域還是在 Match User 塊中)。

有沒有一種相當簡單的方法可以使用 OpenSSH 完成我想要的?也許command=...以聰明的方式使用指令?或者,是否有其他 SFTP 伺服器可以做我想做的事?

編輯:為了更清楚我想要實現的目標:我希望多個客戶端能夠在我的伺服器上儲存文件。每個客戶端都不能看到任何其他客戶端的文件。而且我不想用幾十個使用者帳戶亂扔我的伺服器,所以我想要一個易於管理的解決方案,讓客戶端共享一個使用者帳戶,但仍然無法訪問彼此的文件。

或者,是否有其他 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

注意:文件末尾必須包含新行!這一點很重要。

引用自:https://serverfault.com/questions/758754