ftp的主動和被動模式和vsftp服務

b10l07發表於2018-05-07

一、前言

FTP,File transfer Protocl即檔案傳輸協議,是用於在網路中控制檔案的雙向傳輸的協議。FTP協議執行在TCP/21和20埠,通常來說21埠是命令埠、20埠是資料埠,但根據FTP的工作模式的不同,資料埠也有可能跟著改變。

二、FTP的工作模式

1、主動模式PORT

5294226-96fca45b05c49902.png
主動模式的邏輯圖

如上圖所示,在主動模式下,FTP客戶端從任意埠5150(埠號>1023)發起一個FTP請求,並攜帶自己監聽的埠號5151(傳送的埠號+1=監聽埠號);隨後伺服器返回確認,然後從伺服器本地的20埠主動發起連線請求到客戶端的監聽埠5151,最後客戶端返回確認。
這種模式缺點在於伺服器帶客戶端的FTP連線很容易被傳輸過程中的路由器、防火牆所影響或攔截。

2、被動模式PASV

5294226-729d72d35565dfed.png
被動模式的邏輯圖

為了主動模式所面臨的伺服器到客戶端的連線會被攔截阻塞的問題,FTP發展出了被動模式。在被動模式中,命令連線和資料連線都由客戶端來發起,這樣就可以解決從伺服器到客戶端的資料埠的入方向連線被防火牆攔截的問題。
如上圖所示,客戶端用隨機命令埠5150向伺服器的21命令埠傳送一個PASV請求,然後伺服器返回資料埠3267,告訴客戶端我在哪個埠監聽資料連線。然後客戶端向伺服器的監聽埠3268發起資料連線,最後伺服器回覆確認ok。

三、安裝vsftp服務

1、vsftp的配置檔案

vsftp服務即"Very secure file transfer protocol",是一款結合多種認證手段的ftp開源軟體。
在centos7上安裝vsftp服務:

[root@ftp ~]# yum install -y vsftp
.....
已安裝:
  vsftpd.x86_64 0:3.0.2-22.el7                                                                                  
完畢!

停止firewalld和設定selinux為permissive:

[root@ftp ~]# systemctl stop firewalld
[root@ftp ~]# setenforce 0

vsftpd的程式與配置檔案有:

主程式:/usr/sbin/vsftpd
主配置檔案:/etc/vsftpd/vsftpd.conf
資料根目錄:/var/ftp
Systemd Unit File :/usr/lib/systemd/systemd/vsftpd.service
禁止登陸使用者列表:/etc/vsftpd/ftpusers
使用者列表/etc/vsftpd/user_list

預設情況下,vsftpd的主配置檔案沒有註釋的引數及解析如下:

anonymous_enable=YES  #是否允許匿名使用者訪問
local_enable=YES  #是否允許本地使用者登入FPT
write_enable=YES  #是否允許寫入許可權
local_umask=022  #本地使用者上傳檔案的umask值
dirmessage_enable=YES  #是否在使用者進入某個目錄時,會顯示該目錄需要注意的內容
xferlog_enable=YES  #是否讓FTP伺服器記錄上傳下載的情況
connect_from_port_20=YES  #即預設情況下,FTP PORT主動模式進行資料傳輸時使用20埠(ftp-data)。YES使用,NO不使用。
xferlog_std_format=YES  #是否將記錄的上傳下載情況寫在xferlog_file所指定的檔案中
listen=NO  #是否以獨立執行的方式監聽服務
listen_ipv6=YES  #是否支援ipv6
pam_service_name=vsftpd  #列出與vsftpd相關的pam檔案
userlist_enable=YES  #是否啟用禁止登入使用者名稱單
tcp_wrappers=YES  #是否支援tcp_wrappers

除了預設使用的引數外,主配置檔案還可以設定以下引數:

定義匿名使用者的ftp共享許可權:
  anon_world_readable_only =YES  #是否全域性可讀
  anon_upload_enable=NO #是否允許上傳檔案,僅能上傳檔案不能建立目錄
  anon_mkdir_write_enable=NO    #是否允許建立目錄
  anon_other_write_enable=NO    #是否刪除檔案、刪除目錄
  anon_umask=077    #匿名使用者的umask

定義系統使用者的ftp許可權:
  local_enable=YES  #允許本地使用者訪問(/etc/passwd中的使用者)
  write_enable=YES  #允許寫入許可權,包括修改,刪除
  local_umask=022       #定義本地使用者上傳的檔案的umask
  chroot_local_user=YES  #禁錮所有本地使用者於其家目錄;需事先去除使用者對家目錄的寫許可權;
  chroot_list_enable=YES
  chroot_list_file=/etc/vsftpd/chroot_list  #禁錮列表中檔案存在的使用者於其家目錄中;需事先去除使用者對其家目錄的寫許可權;

控制可登陸vsftpd服務的使用者列表:
  userlist_enable=YES  #啟用/etc/vsftpd/user_list檔案來控制可登陸使用者;
  userlist_deny=NO # NO意味著只允許/etc/vsftpd/user_list檔案裡面的使用者訪問FTP,YES相反

上傳下載速率:
  anon_max_rate=0    #匿名使用者的最大上傳下載速率,0表示無限制
  local_max_rate=0    #本地使用者的最大上傳下載速率,0表示無限制

併發連線數限制:
  max_clients=2000  #standalone下最大的併發連線數
  max_per_ip=50  #設定單個IP的最大連線數

除了上述引數之外,若還想使用更多的引數可以通過man vsftpd.conf來獲取更多的引數資訊。

2、vsftp的驗證方式

vsftp服務為ftp提供了三種認證方式,分別是:匿名使用者認證、本地使用者認證和虛擬使用者認證。匿名使用者認證是指任何人無需認證即可訪問到FTP伺服器;本地使用者認證是指使用FTP伺服器中的使用者賬號密碼進行登入,Linux系統中是指/etc/passwd中的本地使用者;虛擬使用者認證是指使用vsftp服務獨立維護的FTP賬號密碼進行登入訪問。
匿名使用者訪問顧名思義就是所有人都能訪問到FTP伺服器,而本地使用者和虛擬使用者都是需要提供賬號及密碼才能登陸訪問。從安全性來說虛擬使用者是最安全的,因為就算FTP的賬號密碼洩露了,也不會洩露本地的使用者賬號密碼。

這裡我們使用一臺Centos7的FTP伺服器(192.168.0.188)來認證下vsftp的三種認證方式。

  • 匿名使用者認證的配置
    vsftp服務預設就開啟了匿名使用者登入,這裡我們只需要修改匿名使用者的FTP共享許可權及對應訪問目錄的許可權。
    編輯/etc/vsftpd/vsftpd.conf,使用如下引數:
[root@ftp ~]# vim /etc/vsftpd/vsftpd.conf
anonymous_enable=YES
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
anon_umask=022

儲存退出後啟動vsftpd服務:

[root@ftp ~]# systemctl start vsftpd
[root@ftp ~]# systemctl enable vsftpd
Created symlink from /etc/systemd/system/multi-user.target.wants/vsftpd.service to /usr/lib/systemd/system/vsftpd.service.

此時到另一臺linux伺服器上測試下登入ftp服務:

[root@test ~]# yum install -y lftp  #首先安裝lftp程式,用於連線ftp服務
[root@test ~]# lftp 192.168.0.188 
lftp 192.168.0.188:~> ls              
drwxr-xr-x    2 0        0               6 Aug 03  2017 pub
lftp 192.168.0.188:/> cd pub/
lftp 192.168.0.188:/pub> mkdir anon_test
mkdir: Access failed: 550 Create directory operation failed. (anon_test)

此時發現無法建立anon_test目錄,但是我們已經在vsftpd.conf檔案中配置了匿名使用者可建立目錄的引數了,這是因為ftp服務的根目錄我們還沒有對其進行修改。匿名使用者的預設路徑即為ftp使用者的家目錄/var/ftp,而vsftp使用者的真正許可權是vsftpd.conf定義的共享許可權與訪問目錄的許可權的交集。所以此時我們需要去修改/var/ftp/pub目錄的檔案許可權:

[root@ftp ~]# ll -d /var/ftp/pub/  
drwxr-xr-x. 2 root root 6 8月   3 2017 /var/ftp/pub/  #預設情況/var/ftp/pub目錄的屬主和屬組均為root,其他組並沒有寫許可權
[root@ftp ~]# chown ftp:ftp /var/ftp/pub/  #更改/var/ftp/pub目錄的屬主和屬組為ftp

此時重新在ftp客戶端上匿名登入測試:

[root@test ~]# lftp 192.168.0.188 
lftp 192.168.0.188:~> cd pub
cd ok, cwd=/pub
lftp 192.168.0.188:/pub> mkdir anon_test
mkdir ok, `anon_test' created  #test目錄順利建立完成
lftp 192.168.0.188:/pub> lcd /etc/
lcd ok, local cwd=/etc
lftp 192.168.0.188:/pub> put fstab   #測試檔案上傳也成功
465 bytes transferred
lftp 192.168.0.188:/pub> ls
drwx------    2 14       50              6 Apr 23 17:08 anon_test
-rw-------    1 14       50            465 Apr 23 17:09 fstab
lftp 192.168.0.188:/pub> rm fstab #刪除檔案也可以
rm ok, `fstab' removed
lftp 192.168.0.188:/pub> rmdir anon_test/  #刪除目錄頁ok
rmdir ok, `anon_test/' removed
  • 本地使用者認證配置
    vsftp服務預設也是允許了本地使用者認證,我們需要對本地使用者認證後的許可權進行設定:
[root@ftp ~]# vim /etc/vsftpd/vsftpd.conf
anonymous_enable=NO  #先取消匿名登入,以免影響測試
local_enable=YES
write_enable=YES
local_umask=022
userlist_enable=YES
userlist_deny=NO

隨後編輯/etc/vsftpd/user_list使用者檔案:

[root@ftp ~]# vim /etc/vsftpd/user_list# vsftpd userlist
# If userlist_deny=NO, only allow users in this file
# If userlist_deny=YES (default), never allow users in this file, and
# do not even prompt for a password.
# Note that the default vsftpd pam config also checks /etc/vsftpd/ftpusers
# for users that are denied.
charlie  #刪除原有的系統使用者,新增登入本地使用者

編輯儲存後,重啟vsftpd服務:

[root@ftp ~]# systemctl restart vsftpd

隨後在ftp客戶端測試登入:

[root@test ~]# lftp 192.168.0.188 -u charlie
Password: 
lftp charlie@192.168.0.188:~>    
lftp charlie@192.168.0.188:~> pwd
ftp://charlie@192.168.0.188  #此時位於charlie的家目錄中
lftp charlie@192.168.0.188:~> lcd /etc
lcd ok, local cwd=/etc
lftp charlie@192.168.0.188:~> put fstab  #測試上傳檔案成功
465 bytes transferred
lftp charlie@192.168.0.188:~> mkdir local_test  #測試建立目錄成功
mkdir ok, `local_test' created
lftp charlie@192.168.0.188:~> rm fstab  #測試刪除檔案成功
rm ok, `fstab' removed
lftp charlie@192.168.0.188:~> rmdir local_test  #測試刪除目錄成功
rmdir ok, `local_test' removed
lftp charlie@192.168.0.188:~> cd /etc/
cd ok, cwd=/etc                   
lftp charlie@192.168.0.188:/etc> get passwd  #測試下載檔案成功
1553 bytes transferred

上面測試發現,本地使用者能切換到/etc目錄,並且能夠下載passwd檔案,這肯定有安全風險啊,vsftp服務可以讓我們把本地使用者的訪問路徑限制在其對應的家目錄,如:

[root@ftp ~]# vim /etc/vsftpd/vsftpd.conf
chroot_local_user=YES  #找到對應的引數並取消註釋
allow_writeable_chroot=YES  #允許禁錮的FTP根目錄可寫而不拒絕使用者的登入請求
#chroot_list_file=/etc/vsftpd/chroot_list 也可以通過使用者檔案來指定禁錮的使用者範圍

另外,從2.3.5之後,vsftpd增強了安全檢查,如果使用者被限定在了其主目錄下,則該使用者的主目錄不能再具有寫許可權了!如果檢查發現還有寫許可權,就會報錯誤put: Login failed: 500 OOPS: vsftpd: refusing to run with writable root inside chroot()。但是取消了主目錄的寫許可權後,使用者自己本身也不能對主目錄進行修改了,如果還想能在對主目錄擁有寫許可權,可以使用allow_writeable_chroot=YES引數。
此時再次在FTP客戶端測試:

[root@test ~]# lftp 192.168.0.188 -u charlie
Password: 
lftp charlie@192.168.0.188:~>         
lftp charlie@192.168.0.188:~> cd /etc\
> 
lftp charlie@192.168.0.188:/> cd /etc
cd: Access failed: 550 Failed to change directory. (/etc)
lftp charlie@192.168.0.188:/> lcd /etc
lcd ok, local cwd=/etc
lftp charlie@192.168.0.188:/> put fstab 
465 bytes transferred
lftp charlie@192.168.0.188:/> mkdir test
mkdir ok, `test' created
lftp charlie@192.168.0.188:/> rm fstab 
rm ok, `fstab' removed
lftp charlie@192.168.0.188:/> rmdir test
rmdir ok, `test' removed
lftp charlie@192.168.0.188:/> lcd /root/
lcd ok, local cwd=/root
lftp charlie@192.168.0.188:/> get hello 

此時除了無法切換到其他目錄之外,其上傳下載,新增刪除檔案或目錄都能正常進行。

  • 虛擬使用者認證
    因為虛擬使用者認證所使用的賬號和密碼都不是系統中真實存在的,所以其安全性比本地使用者更好。而且因為ftp服務原本就是明文傳輸的,因為如果使用本地使用者認證的話,一般有不好好意之人在客戶端訪問FTP伺服器的路徑之間進行抓包,就能獲取相應的系統本地使用者資訊,這對系統來說是很不安全的。
    虛擬使用者認證的配置步驟比起前兩種認證來說複雜了點,具體流程如下:

1)建立虛擬FTP使用者資料庫檔案
2)建立FTP根目錄及虛擬使用者對映的系統使用者
3)建立支援虛擬使用者的PAM認證檔案
4)在vsftpd.conf中新增支援配置
5)為虛擬使用者設定不同的許可權
6)重啟vsftpd服務,測試結果

1)建立虛擬FTP資料庫檔案

[root@ftp ~]# vim /etc/vsftpd/vuser.list  
#奇數行為賬號,偶數行為密碼
vuser  
123456
magedu
qaz123

[root@ftp ~]# db_load -T -t hash -f /etc/vsftpd/vuser.list /etc/vsftpd/vuser.db  #使用db_load命令結合HASH演算法生成資料庫檔案
[root@ftp ~]# chmod 600 /etc/vsftpd/vuser.db  #敏感檔案限制只允許屬主讀寫
[root@ftp ~]# rm /etc/vsftpd/vuser.list   #刪除原始檔案
rm:是否刪除普通檔案 "/etc/vsftpd/vuser.list"?y

2)建立FTP根目錄及虛擬使用者對映的系統使用者

[root@ftp ~]# useradd -d /var/vuserroot -s /sbin/nologin vftp  #建立系統使用者vftp,並制定其家目錄為/var/vuserroot
[root@ftp ~]# chmod -Rf 755 /var/vuserroot/  #修改目錄的許可權使得其他使用者也可以訪問

3)建立支援虛擬使用者的PAM認證檔案

[root@ftp ~]# vim /etc/pam.d/vsftpd.virtual
auth required pam_userdb.so db=/etc/vsftpd/vuser  #此句用於檢查使用者密碼,資料庫檔案不要寫字尾.db
account required pam_userdb.so db=/etc/vsftpd/vuser  #此句用於檢查使用者是否在有效期內,資料庫檔案不要寫字尾.db

4)在vsftpd.conf中新增支援配置

[root@ftp ~]# vim /etc/vsftpd/vsftpd.conf
anonymous_enable=NO  #禁止匿名登入
local_enable=YES  #允許本地使用者模式,由於對映的系統使用者為本地使用者,因此此項必須開啟
guest_enable=YES  #開啟虛擬使用者模式
guest_username=vftp  #指定虛擬使用者賬號
pam_service_name=vsftpd.virtual  #指定pam檔案
chroot_local_user=YES  #禁錮使用者在其家目錄
allow_writeable_chroot=YES  #允許禁錮的FTP根目錄可寫而不拒絕使用者的登入請求
user_config_dir=/etc/vsftpd/vusers_profile  #指定虛擬使用者的許可權配置目錄
userlist_deny=YES  #此前實驗設定為NO,更改為YES

5)為虛擬使用者設定不同的許可權

[root@ftp ~]# mkdir /etc/vsftpd/vusers_profile
[root@ftp ~]# vim /etc/vsftpd/vusers_profile/vuser
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
[root@ftp ~]# vim /etc/vsftpd/vusers_profile/magedu
local_root=/vftp/magedu  #給虛擬使用者magedu單獨制定根目錄
anon_umask=022  
anon_mkdir_write_enable=YES
anon_upload_enable=YES
anon_other_write_enable=YES
[root@ftp ~]# mkdir -pv /vftp/magedu  #建立magedu虛擬使用者的根目錄
mkdir: 已建立目錄 "/vftp" 
mkdir: 已建立目錄 "/vftp/magedu"
[root@ftp ~]# touch /vftp/magedu/hello
[root@ftp ~]# touch /vftp/magedu/magedu

6)重啟vsftpd服務,測試結果

[root@ftp ~]# systemctl restart vsftpd

在ftp客戶端上測試:

[root@test ~]# lftp 192.168.0.188 -u vuser
Password: 
lftp vuser@192.168.0.188:/> pwd  
ftp://vuser@192.168.0.188/
lftp vuser@192.168.0.188:/> mkdir test  #建立目錄成功
mkdir ok, `test' created
lftp vuser@192.168.0.188:/> lcd /etc
lcd ok, local cwd=/etc
lftp vuser@192.168.0.188:/> put fstab  #上傳檔案成功
465 bytes transferred
lftp vuser@192.168.0.188:/> ls  #
-rw-------    1 1004     1005          465 Apr 23 19:22 fstab
-rw-r--r--    1 0        0               0 Apr 23 19:23 hello
drwx------    2 1004     1005            6 Apr 23 19:22 test
lftp vuser@192.168.0.188:/> get hello #下載檔案成功
lftp vuser@192.168.0.188:~> cd /etc    #無法切換到其他目錄路徑
cd: Access failed: 550 Failed to change directory. (/etc)

[root@test ~]# lftp 192.168.0.188 -u magedu
Password: 
lftp magedu@192.168.0.188:/> pwd 
ftp://magedu@192.168.0.188/
lftp magedu@192.168.0.188:/> cd /etc  #不能切換到其他目錄路徑
cd: Access failed: 550 Failed to change directory. (/etc)
lftp magedu@192.168.0.188:/> cd /var/vuserroot
cd: Access failed: 550 Failed to change directory. (/var/vuserroot)
lftp magedu@192.168.0.188:/> lcd /etc
lcd ok, local cwd=/etc
lftp magedu@192.168.0.188:/> put fstab  #上傳檔案成功
465 bytes transferred
lftp magedu@192.168.0.188:/> mkdir test  #建立目錄成功
mkdir ok, `test' created
lftp magedu@192.168.0.188:/> rmdir test  #刪除目錄成功
rmdir ok, `test' removed
lftp magedu@192.168.0.188:/> rm fstab   #刪除檔案成功
rm ok, `fstab' removed
lftp magedu@192.168.0.188:~> ls
-rw-r--r--    1 0        0               0 Apr 23 19:34 hello
-rw-r--r--    1 0        0               0 Apr 23 19:34 magedu
lftp magedu@192.168.0.188:/> get magedu  #下載檔案成功

相關文章