Arch Linux ARM 安裝與設定 FTP 伺服器 for vsftpd

如何在 Arch Linux ARM 裡安裝 vsftpd 這個 FTP 伺服器,並設定允許使用者登入、上傳的環境,以及如何限制使用者無法離開家目錄,及解說 umask 檔案預設權限與 chroot 限制。

raspberry-pi

以下流程將使用「一般使用者」而非 root 來操作系統,如無法使用 sudo 指令,請參考 安裝與設定 Arch Linux for Raspberry Pi 2
使用 pacman -S 指令安裝套件發生失敗或錯誤時,請先執行 pacman -Sy 更新套件列表資料

基本概念

umask 檔案預設權限

這是在新建目錄或檔案時的預設權限。

umask 的分數是「預設值需要減掉的權限」,而新建目錄或檔案的預設權限值如下:

  • 新建「檔案」:檔案沒有可執行(x)的權限,也就是說只有 rw 這兩個,所以預設權限值為 666 → -rw-rw-rw-
  • 新建「目錄」:因為 x 權限與是否可進入此目錄有關,也就是所有權限均開放,所以預設權限值為 777 → drwxrwxrwx

假設 umask = 022,所以:

  • 新建「檔案」的權限為 666 – 022 = 644
  • 新建「目錄」的權限為 777 – 002 = 755

chroot 限制

為了阻步使用者進入 Linux 系統的其他目錄,也就是將使用者限制在自己的家目錄底下,這樣登入 FTP 後,就無法切換至 Linux 系統的其它目錄了,這種環境就是 chroot 限制,來加強「安全性」。

安裝

使用以下指令安裝 vsftpd 這套 FTP(檔案傳輸協定)伺服器:

[smalljacky@alarmpi ~]$ sudo pacman -S vsftpd

啟動 vsftpd,並設定開機自動啟動:

[smalljacky@alarmpi ~]$ sudo systemctl start vsftpd.service
[smalljacky@alarmpi ~]$ sudo systemctl enable vsftpd.service

測試

使用預設啟用的 anonymous(匿名)測試,先切換至 anonymous 的家目錄,在新增一個 ftptest 檔案,然後使用 ftp 指令 – 連線至 vsftpd 伺服器:

anonymous 的家目錄在 /srv/ftp/,且無上傳權限,並啟用 chroot(將使用者限制在家目錄)
[smalljacky@alarmpi ~]$ cd /srv/ftp/
[smalljacky@alarmpi ftp]$ sudo touch ftptest
[smalljacky@alarmpi ftp]$ ftp localhost

ftp: connect to address ::1: Connection refused
ftp: Trying 127.0.0.1 ...
Connected to localhost.
220 (vsFTPd 3.0.3)

# 使用者名稱
Name (localhost:smalljacky): anonymous

# 無密碼,直接「ENTER」
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

# 查看伺服器的目錄或檔案
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rwxrwxrwx    1 0        0               0 Mar 30 21:25 ftptest
226 Directory send OK.

# 結束 ftp
ftp> bye
221 Goodbye.

設定檔

說明

vsftpd 的設定檔在 /etc/vsftpd.conf,以下列出較常用的一些設定:

[smalljacky@alarmpi ~]$ sudo nano /etc/vsftpd.conf

# 是否啟用 anonymous 登入
anonymous_enable=YES

# 允許 /etc/passwd 中的使用者登入,就是允許使用者登入
# 目錄為 /home/使用登名稱
#local_enable=YES

# 允許使用者修改資料
#write_enable=YES

# 新建目錄或檔案時的預設權限
#local_umask=022

# 是否啟用 chroot,將所有使用者限制在家目錄
# YES 啟用;NO 停用(註釋表示 NO)
#chroot_local_user=YES

# 是否啟用指定使用者,如下 chroot_list_file 設定的路徑
# YES 啟用;NO 停用(註釋表示 NO)
#chroot_list_enable=YES

# 限制或排除指定的使用者,取決於 chroot_local_user 的設定
#chroot_list_file=/etc/vsftpd.chroot_list

這裡最難理解的就是 chroot_local_user、chroot_list_enable 這兩個設定了,下表列出它們的組合效果:

chroot_local_user 與 chroot_list_enable 組合效果
chroot_local_user=YES chroot_local_user=NO
chroot_list_enable=YES
  • 啟用 chroot,將所有使用者限制在家目錄
  • 對 chroot_list_file 指定的使用者,停用 chroot
  • 停用 chroot,所有使用者不被限制在家目錄
  • 對 chroot_list_file 指定的使用者,啟用 chroot
chroot_list_enable=NO
  • 啟用 chroot,將所有使用者限制在家目錄
  • 不使用 chroot_list_file 指定的使用者
  • 停用 chroot,所有使用者不被限制在家目錄
  • 不使用 chroot_list_file 指定的使用者

案例設定

現在有一需求如下:

  1. anonymous 不可登入
  2. 所有使用者都可登入並上傳資料
  3. 僅 smalljacky 使用者,不被限制在家目錄
  4. 新建資料的預設權限:
    • 檔案:644
    • 目錄:755

編輯設定檔:

[smalljacky@alarmpi ~]$ sudo nano /etc/vsftpd.conf

#anonymous_enable=YES
local_enable=YES
write_enable=YES
local_umask=022
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd.chroot_list

設定排除 smalljacky 使用者,停用 chroot:

[smalljacky@alarmpi ~]$ sudo nano /etc/vsftpd.chroot_list

# 一行一個使用者
smalljacky

重新載入設定檔,這樣剛才的設定才能生效:

[smalljacky@alarmpi ~]$ sudo systemctl reload vsftpd.service

停用 chroot 的使用者測試

使用 smalljacky 使用者登入測試,先新增一個 ftptest 檔案,然後使用 ftp 指令 – 連線至 vsftpd 伺服器:

因為在自己的家目錄,所以沒有權限問題,就不需 sudo 指令,即可新增檔案
[smalljacky@alarmpi ~]$ touch ftptest
[smalljacky@alarmpi ~]$ ftp localhost

ftp: connect to address ::1: Connection refused
ftp: Trying 127.0.0.1 ...
Connected to localhost.
220 (vsFTPd 3.0.3)

# 使用者名稱
Name (localhost:smalljacky): smalljacky

# 密碼
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

# 查看目前所在目錄
ftp> pwd
257 "/home/smalljacky" is the current directory

# 查看伺服器的目錄或檔案
ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rwxrwxrwx    1 0        0               0 Mar 30 21:25 ftptest
226 Directory send OK.

# 變更到上一層目錄
ftp> cdup
250 Directory successfully changed.

ftp> dir
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwx------    2 1000     1000         4096 Mar 30 19:19 alarm
drwx------    2 1001     1001         4096 Mar 31 22:44 smalljacky
226 Directory send OK.

# 變更到指定目錄
ftp> cd smalljacky
250 Directory successfully changed.
ftp> pwd
257 "/home/smalljacky" is the current directory

# 結束 ftp
ftp> bye
221 Goodbye.

啟用 chroot 的使用者測試

使用 alarm 使用者登入測試,使用 ftp 指令 – 連線至 vsftpd 伺服器:

[smalljacky@alarmpi ~]$ ftp localhost

ftp: connect to address ::1: Connection refused
ftp: Trying 127.0.0.1 ...
Connected to localhost.localdomain.
220 (vsFTPd 3.0.3)

# 使用者名稱
Name (localhost:smalljacky): alarm

# 密碼
331 Please specify the password.
Password:

# 登入失敗
500 OOPS: vsftpd: refusing to run with writable root inside chroot()
ftp: Login failed.
421 Service not available, remote server has closed connection

# 結束 ftp
ftp> bye

不是已經允許所有使用者登入了嗎?上述登入失敗的說明為“啟用 chroot 環境,使用者的 root(就是家)目錄,不可以有寫入(w)的權限”。

沒有寫入權限不就無法修改檔案了?沒辦法這是 vsftpd 的設計,目前唯一的解法就是取消家目錄的寫入權限,並新增一個目錄,且給予可讀、寫和執行的權限,這裡我新增一個 ftp 的目錄名稱:


[smalljacky@alarmpi ~]$ sudo ls -ald /home/alarm               # 查看目錄權限
drwx------ 2 alarm alarm 4096 Mar 31 03:19 /home/alarm
[smalljacky@alarmpi ~]$ sudo chmod 500 /home/alarm             # 取消寫入(w)的權限
[smalljacky@alarmpi ~]$ sudo ls -ald /home/alarm
dr-x------ 2 alarm alarm 4096 Mar 31 03:19 /home/alarm
[smalljacky@alarmpi ~]$ sudo mkdir -m 700 /home/alarm/ftp      # 新建目錄
[smalljacky@alarmpi ~]$ sudo chown alarm:alarm /home/alarm/ftp # 變更擁有者:群組
[smalljacky@alarmpi ~]$ sudo ls -ald /home/alarm/ftp
drwx------ 2 alarm alarm 4096 Apr  2 13:42 /home/alarm/ftp

再次使用 alarm 使用者登入測試:

[smalljacky@alarmpi ~]$ ftp localhost

ftp: connect to address ::1: Connection refused
ftp: Trying 127.0.0.1 ...
Connected to localhost.localdomain.
220 (vsFTPd 3.0.3)

# 使用者名稱
Name (localhost:smalljacky): alarm

# 密碼
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

# 變更到 ftp 這個目錄
ftp> cd ftp
250 Directory successfully changed.

# 查看目前所在目錄
ftp> pwd
257 "/ftp" is the current directory

# 結束 ftp
ftp> bye
221 Goodbye.

發表迴響