跳至內容

OpenSSH/食譜/使用 SFTP 傳輸檔案

100% developed
來自 Wikibooks,為開放世界提供開放書籍
(從 OpenSSH/食譜/SFTP 重定向)

 

基本 SFTP 服務不需要任何額外的設定,它是 OpenSSH 伺服器的內建部分,它是子系統 sftp-server(8),然後實現 SFTP 檔案傳輸。有關 sftp-server(8) 的更多資訊,請參見手冊頁。或者,子系統 internal-sftp 可以實現一個程序內 SFTP 伺服器,這可以簡化使用 ChrootDirectory 強制客戶端使用不同的檔案系統根目錄的配置。

在客戶端上,SFTP 可用的選項和技巧與常規 SSH 客戶端相同。但是,一些客戶端選項可能必須使用 -o 引數使用完整的選項名稱指定。對於許多專用的圖形 SFTP 客戶端,可以使用常規 URL 指向目標。如今,許多檔案管理器都內建支援 SFTP。請參閱上面的“GUI 客戶端”部分。

基本 SFTP

[編輯 | 編輯原始碼]

SFTP 提供了一個非常易於使用和配置的選項,用於訪問遠端系統。再次說明,常規 SFTP 訪問不需要從預設配置進行任何額外更改。可以使用常用的客戶端,或者使用專用的客戶端,例如 sshfs(1)

自動化 SFTP

[編輯 | 編輯原始碼]

SFTP 上傳或下載可以自動化。前提是 基於金鑰的身份驗證。一旦基於金鑰的身份驗證工作,就可以使用批處理檔案透過 SFTP 執行活動。有關詳細資訊,請參閱 sftp(1) 中的 批處理檔案 選項 -b

$ sftp -b /home/fred/cmds.batch -i /home/fred/.ssh/foo_key_rsa server.example.org:/home/fred/logs/

如果使用連字元 (-) 作為批處理檔名,則 SFTP 命令將從 stdin 讀取。

$ echo "put /var/log/foobar.log" | sftp -b - -i /home/fred/.ssh/foo_key_rsa server.example.org:/home/fred/logs/

可以傳送多個 SFTP 命令,但最好使用批處理檔案模式。

$ echo -e "put /var/log/foobar.log\nput /var/log/munged.log" | sftp -b - -i /home/fred/.ssh/foo_key_rsa server.example.org:/home/fred/logs/

批處理檔案模式在 cron 作業和指令碼中非常有用。

僅 SFTP 帳戶

[編輯 | 編輯原始碼]

使用 sshd_config(5) 中的 Match 指令,可以將特定組的成員限制為僅使用 SFTP 與伺服器互動。

Subsystem sftp internal-sftp

Match Group sftp-only
	AllowTCPForwarding no
	X11Forwarding no
	ForceCommand internal-sftp

請注意,停用 TCP 轉發不會提高安全性,除非使用者也被拒絕訪問 shell,因為他們原則上可以安裝自己的轉發器。

有關可用於 Match 的模式的更多資訊,請參閱 ssh_config(5) 中的模式。

一個帳戶組通常需要讀寫伺服器上其主目錄中的檔案,而很少或根本沒有理由訪問檔案系統的其他部分。SFTP 提供了一個非常易於使用和配置的 chroot。在某些情況下,將使用者 chroot 到其主目錄就足夠了。這可能並不那麼直接,因為在大多數情況下,主目錄不屬於 root 並且允許至少一個使用者寫入。但是,由於 SFTP chroot 要求 chroot 目標目錄和所有父目錄都屬於 root 並且任何其他人不可寫,因此會造成一些困難,但這是必要的。如果沒有所有權限制,則完全有可能逃避 chroot。 [1]

解決此限制帶來的困難的一種方法是讓主目錄屬於 root,並用屬於常規帳戶的許多其他目錄和檔案填充它,該帳戶實際上可以寫入這些目錄和檔案。

Match Group sftp-only
	ChrootDirectory %h
	AllowTCPForwarding no
	X11Forwarding no
	ForceCommand internal-sftp

在這種情況下,root 使用者必須用所需的​​檔案和子目錄填充目標目錄,然後將其所有權更改為非特權帳戶。

為 chrooted 僅 SFTP 帳戶設定許可權的三種方法

[編輯 | 編輯原始碼]

至少有三種其他方法可以為 chrooted 僅 SFTP 帳戶設定主目錄的許可權。它們各有優勢和一些缺點,因此適合某些特定情況,但不適合其他情況。

選項 1:自動設定起始目錄

[編輯 | 編輯原始碼]

如果讓各種主目錄屬於 root 不切實際,可以做出折衷。ChrootDirectory 可以指向 /home(無論如何都必須屬於 root),然後 ForceCommand 可以使用 -d 選項指定使用者的​​主目錄作為起始目錄。

Match Group sftp-only
        ChrootDirectory /home/
        ForceCommand internal-sftp -d %u

在 chroot 下巢狀另一個目錄是另一種方法。子目錄將由非特權帳戶可寫,chroot 目標將不可寫。

Match Group sftp-only
        ChrootDirectory /home/%u
        AllowTCPForwarding no
        X11Forwarding no
        ForceCommand internal-sftp -d %u

如果需要將主目錄的內容隱藏起來,使其對其他使用者不可見,可以使用 chmod(1)。許可權可以是 /home 的 0111 和 0750、0700、0770 或 2770,等等,對於主目錄,務必檢查組成員資格。

選項 2:巢狀的主目錄

[編輯 | 編輯原始碼]

或者,為了獲得類似的效果但更具隔離性,可以將 chrooted 帳戶的主目錄巢狀一層。請注意以下目錄的所有權和許可權

$ ls -lhd /home/ /home/*/ /home/*/*/
drwxr-xr-x  4 root  root  4.0K Aug  4 20:47 /home/
drwxr-x---  3 root  user1 4.0K Aug  4 20:47 /home/user1/
drwxr-x---  3 root  user2 4.0K Aug  4 20:47 /home/user2/
drwxr-x--- 14 user1 user1 4.0K Aug  4 20:47 /home/user1/user1/
drwxr-x--- 14 user2 user2 4.0K Aug  4 20:47 /home/user2/user2/

然後 ChrootDirectory 指令可以將使用者鎖定在他們主目錄的上級目錄,ForceCommand 指令可以使用 -d 選項將使用者置於他們自己的主目錄。登入後,他們只能看到自己的檔案。這種安排還便於以後新增 chrooted shell 訪問許可權,因為系統目錄可以新增到 chroot 中,而其他帳戶無法訪問這些目錄。

另一種常見情況是 chroot 訪問 Web 伺服器的文件根目錄或伺服器根目錄。如果每個站點在 /var/www/ 下都有自己的層次結構,例如 /var/www/site1/,那麼 chroot 可以按如下方式使用

Match Group team1
	ChrootDirectory /var/www/
	ForceCommand internal-sftp -d site1

Match Group team2
	ChrootDirectory /var/www/
	ForceCommand internal-sftp -d site2

然後,站點目錄可以由組寫入,而父目錄 /var/www/ 保持對非 root 使用者只讀。

選項 3:分割主目錄及其內容的所有權

[編輯 | 編輯原始碼]

如上所述,處理 chroot 的 SFTP 服務有幾種方法。第三種方法是將目錄設定為由 root 擁有,屬於另一個組,但該組不可寫。因此,使用以下設定,帳戶“fred”可以以通常的方式登入並使用 chroot 目標中的任何預製子目錄或檔案,但不能向 chroot 目標本身新增任何內容。

$ ls -lhd /home/ /home/fred/ /home/fred/*
drwxr-xr-x  68 root root 4.0K Sep 4 15:40 /home/
drwxr-xr-x  21 root fred 4.0K Sep 4 15:41 /home/fred/
drwxr-xr-x   8 fred fred 4.0K Sep 4 15:44 /home/fred/Documents
drwxr-xr-x   9 fred fred 4.0K Sep 4 15:41 /home/fred/Music
drwxr-xr-x 145 fred fred 4.0K Sep 4 15:41 /home/fred/Pictures
drwxr-xr-x   5 fred fred 4.0K Sep 4 15:41 /home/fred/Videos
drwxr-xr-x  98 fred fred 4.0K Sep 4 15:41 /home/fred/WWW

對於 ssh_config(5) 的對應行將是以下內容,其中帳戶“fred”是“team1”組的成員

Match Group team1
	ChrootDirectory /home/%u
	ForceCommand internal-sftp

這種方法設定起來很快,但缺點是每次要向主目錄新增新目錄或檔案時,都需要系統管理員的干預。即使新檔案或目錄被更改為由非特權帳戶擁有,這也需要 root 許可權才能執行。

Umask

[edit | edit source]

從 OpenSSH 5.4 開始,sftp-server(8) 可以設定 umask 來覆蓋使用者帳戶設定的預設 umask。程序內 SFTP 伺服器 internal-sftp 接受與外部 SFTP 子系統相同的選項。

Subsystem sftp internal-sftp -u 0022

但是,必須記住,umask 只能限制許可權,永遠不會放鬆許可權。

早期版本可以透過使用輔助指令碼執行相同的操作,但這會使 chroot 目錄變得非常複雜。輔助指令碼可以是常規指令碼,也可以嵌入到配置檔案中,但兩者在 chroot 監獄中都不容易使用。獲得支援 umask 的較新版本的 sshd(8) 通常更容易,該 umask 是伺服器配置的一部分。以下是 OpenSSH 5.3 及更早版本中 umask 的內聯輔助指令碼,基於 gilles@ 的一個指令碼

Subsystem sftp /bin/sh -c 'umask 0022; /usr/libexec/openssh/sftp-server'

無論哪種方式,此 umask 僅在伺服器端。客戶端的原始檔案許可權通常(但並不總是)會在計算伺服器上的最終檔案許可權時使用。這取決於客戶端本身。大多數客戶端將檔案許可權傳遞給伺服器,FileZilla 是一個值得注意的例外。因此,許可權通常可以收緊,但不能放鬆。例如,客戶端上模式為 600 的檔案不會自動變為 664 或低於原始 600 的任何其他許可權,無論伺服器端的 umask 如何。除非客戶端沒有轉發許可權,在這種情況下,只有伺服器的 umask 會被使用。因此,對於大多數客戶端,如果您希望上傳檔案具有更寬鬆的許可權,請在上傳之前在客戶端更改它們。

進一步限制 Chrooted SFTP

[edit | edit source]

有幾種額外的常見場景,其中 chroot 訪問許可權進一步限制。

Chrooted SFTP 到共享目錄

[edit | edit source]

另一個常見情況是將一組使用者 chroot 到他們負責的 Web 伺服器的不同級別。出於顯而易見的原因,從監獄內部指向 chroot 監獄外部檔案系統的部分的符號連結無法被 chroot 使用者訪問。因此,如果存在特殊的訪問組合,則必須更仔細地規劃目錄層次結構。請參閱前面有關 chroot 僅 SFTP 帳戶的部分。

在這些型別的目錄中,為多個組提供不同級別的訪問許可權可能很有用。在這種情況下,可能需要 ACL。

僅從特定地址訪問的 Chrooted SFTP 帳戶

[edit | edit source]

可以進行更復雜的匹配。可以允許一組使用者使用 SFTP,但不能使用 shell 登入,只有當他們從特定地址或地址範圍登入時。如果他們從正確的地址登入,則獲得 SFTP 且僅獲得 SFTP,但如果他們嘗試從其他地址登入,則會被完全拒絕訪問。必須考慮兩種情況,即肯定匹配和否定匹配。

Subsystem sftp internal-sftp

Match Group sftp-only, Address 192.0.2.10
        AllowTCPForwarding no
        X11Forwarding no
        ForceCommand internal-sftp
        ChrootDirectory  /home/servers/

Match Group sftp-only, Address *,!192.0.2.10
        DenyGroups sftp-only

請注意,對於否定,必須先指定萬用字元,然後是地址或範圍以將其排除在外。注意空格的有無。透過以 CIDR 地址/掩碼格式指定地址(例如 192.0.2.0/24),可以對地址範圍進行類似的匹配。可以指定任意數量的條件,只有在所有條件都滿足的情況下,後續行中的指令才會生效。

第一個匹配的Match塊是生效的塊,因此在構造條件塊時必須小心,使其適合所需的精確情況。此外,任何不符合Match條件塊的情況都將被忽略。這些情況將獲得一般的配置設定,無論它們是什麼。可以使用伺服器的-T-C選項以及配置來測試特定的使用者和源地址組合,以獲取更多選項。有關更多資訊,請參見除錯伺服器配置部分。

帶日誌記錄的 Chrooted SFTP

[edit | edit source]

如果不使用internal-sftp程序內 SFTP 伺服器,那麼日誌記錄守護程式必須在 chroot 目錄中建立一個套接字,以便sftp-server(8)子系統可以訪問它作為/dev/log,請參見日誌記錄部分。

Chrooted 登入 Shell

[edit | edit source]

為互動式 shell 建立 chroot 監獄很困難。chroot 及其所有元件必須是 root 擁有的目錄,這些目錄不可由任何其他使用者或組寫入。ChrootDirectory必須包含支援使用者會話所需的必要檔案和目錄。對於互動式會話,這至少需要一個 shell(通常是bash(1)ksh(1)sh(1)),以及/dev內部的基本裝置節點,例如null(4)zero(4)stdin(4)stdout(4)stderr(4)arandom(4)tty(4)裝置。路徑可能包含以下在連線的使用者經過身份驗證後執行時擴充套件的標記:%%替換為文字“%”,%h替換為正在身份驗證的使用者的 home 目錄,%u替換為該使用者的使用者名稱。

sshfs(1) - 透過本地資料夾進行 SFTP 檔案傳輸

[edit | edit source]

另一種來回傳輸檔案甚至遠端使用它們的方法是使用sshfs(1)它是一個基於 SFTP 的使用者空間檔案系統客戶端,並利用伺服器的 SFTP 子系統。它可以使遠端伺服器上的目錄可訪問,就好像它是本地檔案系統上的目錄一樣,任何程式都可以訪問它。使用者必須對掛載點具有讀寫許可權才能使用sshfs(1)

以下操作會在 home 目錄中建立掛載點mountpoint(如果不存在)。然後sshfs(1)掛載遠端伺服器。

$ test -d ~/mountpoint || mkdir --mode 700 ~/mountpoint
$ sshfs fred@server.example.org:. ~/mountpoint

讀寫掛載點上的檔案實際上是在向遠端系統傳輸資料或從遠端系統傳輸資料。傳輸消耗的頻寬量可以使用壓縮來減少。如果網路連線有頻寬上限或每單位費用,這可能很重要。但是,如果速度是唯一的問題,如果兩端的處理器繁忙或不夠強大,壓縮會使傳輸速度變慢。唯一確定方法是測試並檢視哪種方法更快。下面,使用-C指定壓縮。

$ sshfs -C fred@server.example.org:. ~/mountpoint

或者嘗試使用除錯輸出

$ sshfs -o sshfs_debug fred@server.example.org:. /home/fred/mountpoint

命名管道無法透過sshfs(1)工作。使用fusermount -u解除安裝這些遠端目錄並關閉 SFTP 會話。

使用 sshfs(1) 和金鑰

[edit | edit source]

ssh_command選項用於將引數傳遞給ssh(1)。在此示例中,它用於使ssh(1)指向用於身份驗證的金鑰以在本地掛載遠端目錄/usr/src,作為/home/fred/src

$ sshfs -o ssh_command="ssh -i /home/fred/.ssh/id_rsa" fred@server.example.org:/usr/src /home/fred/src/

如果可用的金鑰已載入到代理中,那麼ssh(1)應該找到它並代表sshfs(1)使用它,無需干預。


參考資料

[edit | edit source]
  1. "Openssh SFTP Chroot Code Execution". halfdog.net. 2018-01-07. Retrieved 2018-01-09.

 

華夏公益教科書