跳轉到內容

OpenSSH/Cookbook/使用 SFTP 傳輸檔案

100% developed
來自 Wikibooks,開放世界中的開放書籍

 

基本 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) 中的 batchfile 選項 **-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 訪問許可權,因為他們原則上可以安裝自己的轉發器。

請參閱 ssh_config(5) 中的 PATTERNS,以獲取有關 **Match** 可用模式的更多資訊。

通常,一組帳戶需要讀取和寫入伺服器上其主目錄中的檔案,而很少或根本沒有理由訪問檔案系統的其他部分。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** 選項將使用者的 home 目錄指定為啟動目錄。

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,而 home 目錄的許可權可以為 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** 指令可以將使用者鎖定在他們 home 目錄的上級目錄中,而 **ForceCommand** 指令可以使用 **-d** 選項將使用者放到他們自己的 home 目錄中。登入後,他們只能看到自己的檔案。這種安排也有助於後來更容易新增 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:拆分主目錄及其內容的所有權

[編輯 | 編輯原始碼]

如上所示,有幾種方法可以處理 chrooted SFTP 服務。第三種方法是將目錄設定為由 root 所有,在另一個組中,但該組不可寫。因此,使用以下設定,帳戶“fred”可以照常登入並使用任何預製的子目錄或檔案,但不能向 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 許可權才能執行此操作。

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

Subsystem sftp internal-sftp -u 0022

但是,務必記住,umask 只能限制許可權,而不能放鬆許可權。

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

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

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

進一步限制 Chroot SFTP

[編輯 | 編輯原始碼]

在 chroot 訪問進一步限制的幾種常見情況下。

Chroot SFTP 到共享目錄

[編輯 | 編輯原始碼]

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

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

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

[編輯 | 編輯原始碼]

可以執行更復雜的匹配。可以允許一組使用者使用 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 選項使用配置測試特定使用者和源地址組合,以獲取更多選項。有關詳細資訊,請參閱部分除錯伺服器配置

帶有日誌記錄的 Chroot SFTP

[編輯 | 編輯原始碼]

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

Chroot 登入 Shell

[編輯 | 編輯原始碼]

為互動式 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 將替換為正在身份驗證的使用者的主目錄,%u 將替換為該使用者的使用者名稱。

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

[編輯 | 編輯原始碼]

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

以下操作將在主目錄中建立掛載點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)

[編輯 | 編輯原始碼]

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) 使用它,無需人工干預。


參考資料

[編輯 | 編輯原始碼]
  1. "Openssh SFTP Chroot Code Execution". halfdog.net. 2018-01-07. Retrieved 2018-01-09.

 

華夏公益教科書