﻿# 透過 OpenSSH 使用 SFTP 登入時將帳戶設為 chroot 的方法 (Linux)

當使用 [WinSCP](http://winscp.net/eng/docs/lang:cht) 或 [FileZilla Client](http://filezilla-project.org/download.php) 使用 SFTP 協定登入 OpenSSH 伺服器時，在預設的情況下使用者可以自由的在檔案系統間遊走，當我們基於安全的理由希望透過 SFTP 登入伺服器後能透過 chroot() 的方法將使用者 **關在**(**chroot**) 特定目錄下，讓他不能跑到其他目錄瀏覽資料，透過一些簡單的設定就能達到，以下就是設定的方式。

下圖是用 [WinSCP](http://winscp.net/eng/docs/lang:cht) 登入 SFTP 伺服器後的畫面，預設路徑在 /home/test01 家目錄 (Home Directory) ，所以使用者可以回到上一層進入 /home 目錄，或進入到任何有權限的目錄，例如使用者可以進入 /etc 查看所有系統設定等等，這不是我們樂見的。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/8fa43c7fdcd3146a6703-image_1004.png)

因此我在系統管理上的需求如下：

-   不允許使用者登入 Shell 進行操作 ( 讓使用者只能使用 SFTP 傳輸檔案 )
-   不允取使用者建立 SSH 通道 (SSH Tunnel 或稱 TCP Forwarding)
-   不允取使用者建立 X11 Forwarding
-   登入後需透過 chroot 限制存取目錄

要達到以上需求，我們必須修改 OpenSSH 的設定檔，並且在建立帳號時設定正確的參數，以及建立一個擁有者為 root 的 Chroot 目錄才行，以下是詳細的設定步驟說明：

**1\. 新增一個 SFTP 專用的群組**

在這裡我們先建立一個 sftponly 群組（你當然也可以建立其他的名稱）

```
addgroup --system sftponly
```

**2\. 修改 OpenSSH 的設定檔**

編輯 "/etc/ssh/sshd\_config" 檔案，先找到以下 Subsystem 設定：

```
Subsystem sftp /usr/lib/openssh/sftp-server internal-sftp
```

並修改成：

```
Subsystem sftp internal-sftp
```

然後在該設定檔最後加上以下設定，其中的 **[ChrootDirectory](http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config&sektion=5)** 設定的 %u 代表使用者帳號：

```
Match group sftponly         ChrootDirectory /home/%u         X11Forwarding no         AllowTcpForwarding no         ForceCommand internal-sftp
```

**3\. 建立新使用者，並加入 sftponly 群組**

建立新使用者後，預設會建立 /home/*USERNAME* 家目錄 (Home Directory)：

```
adduser sftpuser
```

由於我們在 sshd\_config 設定檔中有宣告只要符合 sftponly 群組的使用者都套用 ChrootDirectory 的設定，因此必須將該使用者加入到 sftponly 群組中：

```
adduser sftpuser sftponly
```

另一個重點是，由於要套用 chroot() 的關係，該使用者登入後的根目錄必須擁有一些必要的目錄，為了節省設定上的麻煩，我們只要將該使用者的家目錄修改為根目錄 ( / ) 即可：

```
usermod -d / sftpuser
```

**4\. 修正使用者帳戶的家目錄權限**

也是由於 chroot() 的特殊限制，這個要 chroot() 目錄的擁有者必須為 root，而且該目錄的權限也必須設定為 755 才行：

```
chown root.root /home/sftpuserchmod 755 /home/sftpuser
```

這裡沒有設定正確的話將永遠無法成功登入，像我第一次設定時就遇到了以下錯誤： ( /var/log/auth.log )

```
sshd[8636]: pam_unix(sshd:session): session opened for user sftpuser by (uid=0)sshd[8707]: fatal: bad ownership or modes for chroot directory "/home/sftpuser"sshd[8636]: pam_unix(sshd:session): session closed for user
```

**5\. 在使用者目錄下建立允許上傳檔案的目錄，並賦予適當的目錄權限**

這一個步驟也是蠻重要的，因為 chroot() 過的目錄擁有者必須為 root 且目錄權限為 755，所以使用者登入後一定無法上傳任何檔案到這個目錄，若要讓使用者能上傳檔案，則必須先幫使用者建立好適當的目錄與設定權限才能夠上傳檔案：

```
cd /home/sftpusermkdir uploadchown sftpuser.sftpuser upload
```

由於該帳戶只需讓使用者上傳檔案，不允許使用者登入使用 shell，所以也建議將一些家目錄內的隱藏檔刪除，以免使用者透過 [WinSCP](http://winscp.net/eng/docs/lang:cht) 或 [FileZilla Client](http://filezilla-project.org/download.php) 登入時看到一些奇怪的檔案。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/dbea3291a9509b11e65b-image_1005.png)

經過幾個簡單的設定過程，就能夠給客戶使用安全的檔案傳輸功能，又能兼顧開放 SSH 的安全性！

**相關連結**

-   [WinSCP :: 什麼是 WinSCP](http://winscp.net/eng/docs/lang:cht)
-   [OpenSSH SFTP chroot() with ChrootDirectory](http://www.debian-administration.org/articles/590)
-   [Chroot in OpenSSH](http://undeadly.org/cgi?action=article&sid=20080220110039)
