前言
FTP(File transfer Protocl),文件傳輸協議,用於在網絡上進行文件傳輸的一套標准協議,使用客戶/服務器模式,屬於網絡傳輸協議的應用層。FTP服務運行在TCP/21和20端口,通常來說21端口是連接端口,20端口是數據端口。
FTP有兩種工作模式,主動模式和被動模式:
- 主動模式:由服務器創建連接,建立的過程描述如下:
客戶端發起請求:
Client:50000(大於1023的端口號) –> Server: 21
服務端建立數據傳輸:
Server: 20/tcp –> Client: 50000+1(客戶端請求端口號+1)
- 被動模式:由客戶端創建連接,建立的過程描述如下:
客戶端發起請求:
Client:50000(大於1023的端口號) –> Server: 21
客戶端建立數據傳輸:
Client:50000+1(客戶端請求端口號+1) –> Server: 隨機端口
實現FTP
- 通過開源軟件 vsftp(Very secure file transfer protocol) 實現ftp:
[root@server ~]# lsb_release -r
Release: 7.2.1511
[root@server ~]# yum -y install vsftpd
[root@server ~]# rpm -qi vsftpd
Name : vsftpd
Version : 3.0.2
Release : 22.el7
Architecture: x86_64
- 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
- 其中主配置文件 /etc/vsftpd/vsftpd.conf 的默認配置:
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 #是否使用20端口進行數據傳輸 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的名單 chroot_list_file=/etc/vsftpd/chroot_list #是否限制在主目錄下的用戶名單 注意:當chroot_local_user=YES和chroot_list_enable=YES時,chroot_list中的用戶都是不受限制的用戶;當chroot_local_user=NO和chroot_list_enable=YES時,chroot_list中的用戶都是受限制的用戶。 控制可登陸vsftpd服務的用戶列表: userlist_enable=YES #啟用/etc/vsftpd/user_list文件來控制可登陸用戶; userlist_deny=NO #NO意味着/etc/vsftpd/user_list為白名單,YES為黑名單 上傳下載速率: anon_max_rate=0 #匿名用戶的最大上傳下載速率,0表示無限制 local_max_rate=0 #本地用戶的最大上傳下載速率,0表示無限制 並發連接數限制: max_clients=2000 #standalone下最大的並發連接數 max_per_ip=50 #設置單個IP的最大連接數
注意:通過 man vsftpd.conf 可以獲取更多參數信息。
- vsftp的3中認證方式:
vsftp服務為ftp提供了3種認證方式,分別是:匿名用戶認證、本地用戶認證和虛擬用戶認證。匿名用戶認證是指任何人無需認證即可訪問到FTP服務器;本地用戶認證在Linux系統中是指/etc/passwd中的用戶;虛擬用戶認證是指使用vsftp服務獨立維護的FTP賬號密碼進行登錄訪問。從安全性來說虛擬用戶是最安全的,因為就算FTP的賬號密碼泄露了,也不會泄露本地的用戶賬號密碼。
1. 匿名用戶
vsftp服務默認就開啟了匿名用戶登錄,此處修改配置文件/etc/vsftpd/vsftpd.conf:
# 備份配置文件
[root@server ~]# cp /etc/vsftpd/vsftpd.conf{,.bak}
[root@server ~]# vim /etc/vsftpd/vsftpd.conf
anonymous_enable=YES
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
local_umask=022
[root@server ~]# setenforce 0
[root@server ~]# systemctl stop vsftpd.service
[root@server ~]# systemctl start vsftpd
[root@server ~]# ss -tan
LISTEN 0 32 :::21 :::*
LISTEN 0 128 :::22 :::*
客戶端進行測試:
[root@client ~]# lftp 192.168.4.119
lftp 192.168.4.119:~> ls
drwxr-xr-x 2 0 0 6 Aug 03 2017 pub
lftp 192.168.4.119:/> cd pub/
lftp 192.168.4.119:/pub> mkdir test
mkdir: Access failed: 550 Create directory operation failed. (test)
lftp 192.168.4.119:/pub> exit
創建test目錄失敗。匿名用戶的默認路徑即為ftp用戶的家目錄/var/ftp,雖然我們已經配置了anon_mkdir_write_enable=YES,但ftp用戶的真正權限是vsftpd.conf定義的共享權限與訪問的目錄的權限的交集,因此我們需要去修改/var/ftp/pub目錄的文件權限:
[root@server ~]# ll -d /var/ftp/pub
drwxr-xr-x. 2 root root 6 Aug 3 2017 /var/ftp/pub
[root@server ~]# chown ftp:ftp /var/ftp/pub/
[root@server ~]# ll -d /var/ftp/pub
drwxr-xr-x. 2 ftp ftp 6 Aug 3 2017 /var/ftp/pub
注意,不能直接修改/var/ftp的屬主屬組為ftp,不然客戶端重新匿名登錄ftp時,會出現報錯:500 OOPS: vsftpd: refusing to run with writable root inside chroot()
重新登錄測試:
[root@\client ~]# lftp 192.168.4.119 lftp 192.168.4.119:~> cd pub/ lftp 192.168.4.119:/pub> mkdir test mkdir ok, `test' created lftp 192.168.4.119:/pub> lcd /etc #切換客戶端的目錄 lcd ok, local cwd=/etc lftp 192.168.4.119:/pub> put passwd 2538 bytes transferred lftp 192.168.4.119:/pub> ls -rw------- 1 14 50 2538 Jun 27 05:44 passwd drwx------ 2 14 50 6 Jun 27 05:43 test lftp 192.168.4.119:/pub> rm passwd rm ok, `passwd' removed lftp 192.168.4.119:/pub> rmdir test rmdir ok, `test' removed lftp 192.168.4.119:/pub> exit
2. 本地用戶
編輯主配置文件/etc/vsftp/vsftp.conf:
[root@server ~]# vim /etc/vsftpd/vsftpd.conf anonymous_enable=NO local_enable=YES write_enable=YES local_umask=022 userlist_enable=YES userlist_deny=NO 注意:當userlist_enable=YES而userlist_deny=NO時,/etc/vsftpd/user_list為白名單;當userlist_enable=YES和userlist_deny=YES時,/etc/vsftpd/user_list為黑名單
編輯/etc/vsftpd/user_list:
[root@server ~]# vim /etc/vsftpd/user_list testftp [root@server ~]# useradd testftp [root@server ~]# echo 123456 | passwd --stdin testftp [root@server ~]# systemctl restart vsftpd
客戶端測試:
[root@\client ~]# lftp 192.168.4.119 -u testftp Password: lftp testftp@192.168.4.119:~> lcd /etc lcd ok, local cwd=/etc lftp testftp@192.168.4.119:~> put passwd 2538 bytes transferred lftp testftp@192.168.4.119:~> mkdir test mkdir ok, `test' created lftp testftp@192.168.4.119:~> ls -rw-r--r-- 1 1001 1001 2538 Jun 27 07:04 passwd drwxr-xr-x 2 1001 1001 6 Jun 27 07:04 test lftp testftp@192.168.4.119:~> rm passwd rm ok, `passwd' removed lftp testftp@192.168.4.119:~> rmdir test rmdir ok, `test' removed lftp testftp@192.168.4.119:~> lcd / lcd ok, local cwd=/ lftp testftp@192.168.4.119:~> cd /etc #切換到服務器的/etc目錄 cd ok, cwd=/etc lftp testftp@192.168.4.119:/etc> get passwd #獲取服務器的/etc/passwd 2583 bytes transferred lftp testftp@192.168.4.119:/etc> exit
本地用戶能切換到/etc目錄能夠下載passwd文件,存在極大風險,因此我們需要把本地用戶的訪問路徑限制在其對應的家目錄下:
[root@server ~]# vim /etc/vsftpd/vsftpd.conf chroot_local_user=YES allow_writeable_chroot=YES #chroot_list_file=/etc/vsftpd/chroot_list 通過文件指定禁錮的用戶 注意:從2.3.5之后,vsftpd增強了安全檢查,如果用戶被限定在了其主目錄下,則該用戶的主目錄不能再具有寫權限了,客戶端執行寫操作時會出現提示:500 OOPS: vsftpd: refusing to run with writable root inside chroot()。
此時如果還想能在對主目錄擁有寫權限,可以使用allow_writeable_chroot=YES。
客戶端測試:
[root@\client ~]# lftp 192.168.4.119 -u testftp
Password:
lftp testftp@192.168.4.119:~> cd /etc
cd: Access failed: 550 Failed to change directory. (/etc)
lftp testftp@192.168.4.119:/> lcd /etc
lcd ok, local cwd=/etc
lftp testftp@192.168.4.119:/> put passwd
2538 bytes transferred
lftp testftp@192.168.4.119:/> mkdir test
mkdir ok, `test' created
lftp testftp@192.168.4.119:/> rm passwd
rm ok, `passwd' removed
lftp testftp@192.168.4.119:/> rmdir test
rmdir ok, `test' removed
lftp testftp@192.168.4.119:/> exit
3. 虛擬用戶
虛擬用戶認證所使用的賬號和密碼都不是服務器中真實存在的,其安全性比本地用戶更好,即使被抓包獲取到賬號密碼都無法直接登錄到服務器。配置虛擬用戶的流程如下:
1)建立虛擬用戶數據庫文件
2)創建根目錄及虛擬用戶映射的系統用戶
3)建立支持虛擬用戶的PAM認證文件
4)在vsftpd.conf中添加支持配置
5)為虛擬用戶設置不同的權限
1)建立虛擬用戶數據庫文件
[root@ftp ~]# vim /etc/vsftpd/vuser
#格式:一行賬號名,一行密碼
test1
123456
test2
12345678
[root@ftp ~]# db_load -T -t hash -f /etc/vsftpd/vuser /etc/vsftpd/vuser.db #使用db_load命令生成數據庫文件
[root@ftp ~]# chmod 600 /etc/vsftpd/vuser.db
[root@ftp ~]# rm /etc/vsftpd/vuser
2)創建根目錄及虛擬用戶映射的系統用戶
[root@server ~]# useradd -d /var/vftp -s /sbin/nologin vftp [root@server ~]# chmod -R 755 /var/vftphome
3)建立支持虛擬用戶的PAM認證文件
[root@server ~]# 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 #檢查用戶是否在有效期內
4)在vsftpd.conf中添加支持配置
[root@server ~]# vim /etc/vsftpd/vsftpd.conf anonymous_enable=NO #禁止匿名登錄 local_enable=YES #允許本地用戶模式,由於映射的系統用戶為本地用戶,因此此項必須開啟 guest_enable=YES #開啟虛擬用戶模式 guest_username=vftp #指定虛擬用戶賬號映射到本地賬號vftp pam_service_name=vsftpd.virtual #指定pam文件 chroot_local_user=YES #禁錮用戶在其家目錄 allow_writeable_chroot=YES #允許禁錮的FTP根目錄可寫 user_config_dir=/etc/vsftpd/vuser_profile #指定虛擬用戶的權限配置目錄 userlist_enable=YES userlist_deny=YES
5)為虛擬用戶設置不同的權限
[root@server ~]# mkdir /etc/vsftpd/vuser_profile [root@server ~]# vim /etc/vsftpd/vuser_profile/test1 anon_upload_enable=YES anon_mkdir_write_enable=YES anon_other_write_enable=YES anon_umask=022 [root@server ~]# vim /etc/vsftpd/vuser_profile/test2 local_root=/vftp/test2 anon_umask=022 anon_mkdir_write_enable=YES anon_upload_enable=YES anon_other_write_enable=YES [root@ftp ~]# mkdir -pv /vftp/test2
[root@ftp ~]# chown vftp:vftp /vftp/test2 [root@ftp ~]# systemctl restart vsftpd
客戶端測試:
#用戶test1 [root@\client ~]# lftp 192.168.4.119 -u test1 Password: lftp test1@192.168.4.119:~> lcd /etc lcd ok, local cwd=/etc lftp test1@192.168.4.119:~> put passwd 2538 bytes transferred lftp test1@192.168.4.119:/> mkdir test mkdir ok, `test' created lftp test1@192.168.4.119:/> ls -rw-r--r-- 1 1002 1002 2538 Jun 27 09:40 passwd drwxr-xr-x 2 1002 1002 6 Jun 27 09:40 test lftp test1@192.168.4.119:/> rm passwd rm ok, `passwd' removed lftp test1@192.168.4.119:/> rmdir test/ rmdir ok, `test/' removed lftp test1@192.168.4.119:/> cd /etc cd: Access failed: 550 Failed to change directory. (/etc) lftp test1@192.168.4.119:/> exit 注意:test1的目錄路徑:/var/vftp,即 服務器創建的系統用戶vftp家目錄。 #用戶test2 [root@\client ~]# lftp 192.168.4.119 -u test2 Password: lftp test2@192.168.4.119:~> lcd /etc lcd ok, local cwd=/etc lftp test2@192.168.4.119:~> put passwd 2538 bytes transferred lftp test2@192.168.4.119:/> mkdir test mkdir ok, `test' created lftp test2@192.168.4.119:/> ls -rw-r--r-- 1 1002 1002 2538 Jun 27 09:46 passwd drwxr-xr-x 2 1002 1002 6 Jun 27 09:46 test lftp test2@192.168.4.119:/> rm passwd rm ok, `passwd' removed lftp test2@192.168.4.119:/> rmdir test/ rmdir ok, `test/' removed lftp test2@192.168.4.119:/> put fstab 477 bytes transferred lftp test2@192.168.4.119:/> lcd / lcd ok, local cwd=/ lftp test2@192.168.4.119:/> get fstab 477 bytes transferred lftp test2@192.168.4.119:~> cd /etc cd: Access failed: 550 Failed to change directory. (/etc) lftp test2@192.168.4.119:/> exit