FTP(檔案傳輸協定, File Transfer Protocol)顧名思義,是專門用來傳輸檔案的通訊協定,並且這個檔案傳輸的方向是雙向的,換句話說,FTP伺服器可以提供檔案給客戶端,客戶端也可以上傳檔案到FTP伺服器上。vsftpd、pureftpd、proftpd都是在Linux作業系統上很流行的FTP伺服器軟體,其中的vsftpd最輕巧,並以安全和效能為重。
安裝vsftpd
要在Ubuntu Server上安裝vsftpd,可以直接在終端機中執行以下指令:
vsftpd監聽的TCP連接埠為FTP預設的21,可以使用以下指令來查看vsftpd是否有確實安裝成功。
ss
指令可以顯示出Socket相關的資訊。-l
參數可以只顯示正在監聽中的連線。若使用ss
指令時都沒給任何參數的話,會忽略掉監聽中的連線。-t
參數可以只顯示TCP連線。-n
參數可以讓連接埠數字直接被輸出,而不是用一個名稱代替。-p
參數可以顯示佔用連線的行程。
如上圖,如果有看到TCP有在監聽連接埠21,就表示vsftpd安裝成功了!這個連接埠21是開在IPv6,但它也可以處理IPv4的連線。
FTP連線的主動模式和被動模式
FTP連線時有主動模式和被動模式。這兩種模式都會建立出兩個TCP連線,原先FTP伺服器開啟的連接埠21,在這兩種模式下都是用來接收客戶端發送查詢檔名、建立目錄、下載檔案、上傳檔案等等的FTP命令用的。
主動模式(Active Mode)
在主動模式下,客戶端與FTP伺服器的連接埠21進行連線後,會尋找一個可用的TCP連接埠並實施監聽。接著客戶端會再透過FTP伺服器的連接埠21,傳送夾帶了IP位址和連接埠資訊的PORT
命令給FTP伺服器,用以告知FTP伺服器客戶端自己另外開啟了哪個連接埠。FTP伺服器就會根據從客戶端發送的IP位址和連接埠訊息「主動」去與客戶端再建立出一個新的連線,這個連線便會被用來進行資料的傳輸,且這個連線在FTP伺服器上的連接埠預設會是20。
一般來說,伺服器會設定防火牆,限制只接受從哪幾個連接埠進入的連線,而不會去限定伺服器主動發出的連線一定要透過哪幾個連接埠,所以伺服器端在這個模式下並不太會出現什麼問題。但對於客戶端來說,客戶端提供給FTP伺服器的IP位址必須要真的能夠被連入,像是客戶端若是經由NAT(Network Address Translation)來連上網路,在沒有特別的設定下,外部的設備均無法由客戶端提供的IP位址來連到客戶端。再加上客戶端的網路環境可能也會有防火牆存在,會把來自FTP伺服器的連線請求阻擋掉,這也是需要再另外設定的。
綜上所述,由於主動模式需要客戶端進行額外的設定,偏偏客戶端的操作者通常是不懂網路或是無權操作網路設定的一般百姓。因此FTP站若是開放給大眾使用,其實並不常用主動模式來連線。
被動模式(Passive Mode)
在被動模式下,客戶端與FTP伺服器的連接埠21進行連線後,客戶端會再透過FTP伺服器的連接埠21,傳送PASV
命令給FTP伺服器。FTP伺服器會尋找一個可用的TCP連接埠並實施監聽,然後會再透過連接埠21將新開的連接埠回應給客戶端,客戶端便可以利用這個連接埠再與FTP伺服器建立另外的新連線,而這個新連線會被用來進行資料的傳輸。
在被動模式下,伺服器端的防火牆就需要去設定允許FTP資料連線用的連接埠可以被連入,而客戶端則通常不需要做任何設定就可以與FTP伺服器建立完整的FTP連線。因此FTP站若是開放給大眾使用,經常會用被動模式來連線。
然而,由於FTP伺服器在每次連接埠21建立新連線後,都需要去開啟其它可用的TCP連接埠並實施監聽,當可用的TCP連接埠被用完,就無法再建立新的FTP連線了。
FTP實際的連線方式
許多FTP客戶端會同時嘗試使用兩種連線模式來建立FTP連線。
一開始客戶端與FTP伺服器的連接埠21進行連線後,會尋找一個可用的TCP連接埠並實施監聽,接著傳送PORT
命令給FTP伺服器。如果FTP伺服器成功與客戶端建立新的資料連線了,就繼續使用主動模式;如果FTP伺服器無法成功與客戶端建立新連線,客戶端就會再傳送PASV
命令給FTP伺服器,使用被動模式進行連線。
設定vsftpd
vsftpd的主設定檔為/etc/vsftpd.conf
。它預設的模樣長成這樣:
其中最重要的設定項目為listen
和listen_ipv6
,分別對應著監聽IPv4還是IPv6(監聽任意網路介面的話也能處理IPv4的連線),它們可以控制vsftpd的啟動方式,看是要用持續啟動的「獨立運行(standalone)」(設為YES
),還是要在需要時(on demand)才由「超級服務(super daemon)」來啟動(設為NO
)。
如果主機是以跑FTP服務為主,那就將listen
或listen_ipv6
設為YES
,反應會比較快;如果不是的話,將listen
和listen_ipv6
設為NO
,可以節省記憶體,當然我們還需要另外設定超級服務來觸發vsftpd的啟動。預設值是listen = NO
、listen_ipv6 = YES
。也就是說,vsftpd預設是以獨立運行的方式啟動的。
若vsftpd是以獨立運行的方式來啟動,則還可以用listen_address
或listen_address6
項目來設定要監聽的網路介面的IP位址。要特別注意的是,listen
或listen_ipv6
項目不能夠同時是YES
。如果要分別監聽不同的IPv4和IPv6的網路介面,則要用不同的設定同時啟動兩個vsftpd,而這個部份就不在本篇文章的探討範圍內了。其實將listen_address6
設為YES
再用防火牆來擋連線會比較省事。
若vsftpd不主動監聽TCP連接埠,而是靠超級服務來啟動,設定起來會比較複雜一點。在下面這一個獨立的小節來探討。
以超級服務(xinetd為例)來啟動vsftpd
若您想要讓vsftpd以獨立運行方式來啟動,請略過這個小節。
常用的超級服務為xinetd(Extended Internet Service Daemon),Ubuntu Server預設並沒有安裝xinetd。
安裝xinetd
要在Ubuntu Server上安裝xinetd,可以直接在終端機中執行以下指令:
設定xinetd
xinetd的設定檔位於/etc/xinetd.d
目錄中,通常一個檔案用來設定一個服務。我們可以在這個目錄底下建立vsftpd
檔案,並將檔案內容填寫如下:
service ftp { server = /usr/sbin/vsftpd socket_type = stream wait = no user = root nice = 10 instances = 64 per_source = 7 disable = no # bind = 192.168.0.1 }
以上設定中service ftp
的ftp
必須要存在於/etc/services
檔案中,預設是21/tcp
。也就是說,xinetd會去監聽TCP連接埠21的連線,並用上面的設定來處理這個連線。
server
項目用來設定xinetd接到連線之後,要把這個連線交給哪個程式(路徑)進行處理。/usr/sbin/vsftpd
即為vsftpd的執行檔路徑。
socket_type
項目是指xinetd與server
項目設定的程式建立的Socket類型。stream
即SOCK_STREAM
,會建立穩定的TCP連線。
wait
項目設定xinetd是否需等到上次連線處理完之後,再去執行server
項目設定的程式。
user
項設定執行server
項目設定的程式的行程屬於哪個使用者。如果沒有設定group
項目的話,group
項目的值會和user
項目一樣。
nice
項目設定執行server
項目設定的程式的行程的nice值。既然都已經是透過超級服務來執行vsftpd,通常我們也不希望vsftpd的優先權太高而影響到其它重要的服務,所以會設定高一點的nice值。
instances
項目設定最多同時處理幾組FTP連線。per_source
項目設定同一IP最多同時允許幾組FTP連線,其實也就影響著同一個IP最多可以上傳和下載幾個檔案啦!
disable
項目設為no
表示要啟用這個service
區塊設定;設為yes
表示要禁用這個service
區塊設定。
bind
項目可以設定這個service
區塊要監聽來自哪個網路介面IP位址的連線。如果不設定就是任意的網路介面。前面加井字號#
是要註解掉這行設定。
套用xinetd的新設定
執行以下指令就可以重新載入xinetd的設定檔:
執行以下指令檢查xinetd是否有在監聽TCP連接埠21:
如上圖,如果有看到TCP有在監聽連接埠21,就表示xinetd設定成功了!這個連接埠21是開在IPv6,但它也可以處理IPv4的連線。
vsftpd的其它設定項目
回到vsftpd的主設定檔/etc/vsftpd.conf
。其它比較重要的設定項目有以下幾個:
use_localtime
:設定是否使用FTP伺服器設定的時區來顯示時間。預設是YES
。connect_from_port_20
:設定是否固定使用連接埠20作為主動模式連到客戶端時使用的連接埠。預設是YES
。write_enable
:設定是否允許本地端的Linux使用者(一般使用者)更動(新增、修改、刪除)FTP伺服器上的檔案。不設定的話表示不允許。local_umask
:設定一般使用者的umask。不設定的話同077
。也就是說建立檔案時的檔案權限會是600
(666 - 077),建立目錄時的檔案權限會是700
(777 - 077)。user_sub_token
:指定一個代表使用者名稱的「記號」(token)。local_root
:修改一般使用者登入後最先進入的目錄路徑。不設定或是設定的目錄不存在的話會進入家目錄。目錄路徑中可以包含user_sub_token
項目所設定的token,假設這個token是設為$USER
,而目錄路徑設為/home/$USER/ftp
,表示使用者登入後要立即進入家目錄下的ftp
目錄中chroot_local_user
、chroot_list_enable
:修改一般使用者透過FTP登入後所能到達的根目錄。不設定的話表示不修改,也就是以Linux作業系統的/
作為根目錄。本篇文章後面會再介紹這幾個項目的設定方式。anonymous_enable
:設定是否允許匿名登入。也就是不需帳號密碼就可以登入FTP站台。預設是NO
,不允許。若想直接透過FTP網址來提供檔案給別人的話,就要允許這個項目。anon_root
:設定匿名使用者的根目錄。不設定就無法讓匿名使用者存取檔案。要注意的是,任何使用者(包括一般使用者和匿名使用者)對其根目錄都不能有寫入權限,所以作為匿名使用者根目錄的目錄,其others不能加上寫入權限。若匿名使用者需要上傳檔案,就只能上傳檔到有對others開啟寫入權限的子目錄中,不能直接傳到根目錄。anon_umask
:設定匿名使用者的umask。不設定的話同077
。anon_upload_enable
:設定匿名使用者是否也可以跟著一般使用者擁有上傳檔案的權限。不設定的話表示不允許。anon_mkdir_write_enable
:設定匿名使用者是否也可以跟著一般使用者擁有建立目錄的權限。不設定的話表示不允許。anon_other_write_enable
:設定匿名使用者是否也可以跟著一般使用者擁有除了上傳檔案和建立目錄之外的其它修改權限。不設定的話表示不允許。anon_max_rate
:限制全部匿名使用者的總連線速度(位元組/秒)。不設定的話表示不限制。chown_uploads
、chown_username
:設定匿名使用者上傳檔案後,要自動將檔案的擁有者改為哪個真實存在的使用者。不設定的話表示不修改,就會用ftp
作為擁有者和群組。local_enable
:設定是否允許使用一般使用者帳號登入FTP站台。預設是YES
,允許。如果將這個項目設為NO
,那麼就只可以允許使用匿名使用者來登入FTP站台。pasv_enable
:設定是否允許被動模式。不設定的話表示允許。pasv_min_port
、pasv_max_port
:設定被動模式時,監聽資料連線可用的連接埠範圍。不設定的話表示沒有範圍限制。accept_timeout
:設定建立被動連線模式時的逾時時間(秒)。不設定的話當作60
。建議將這個值設為小於60
的值,避免伺服器的連接埠被長時間佔用。connect_timeout
:設定建立主動連線模式時的逾時時間(秒)。不設定的話當作60
。idle_session_timeout
:設定客戶端多久(秒)沒發送命令就斷開與FTP伺服器連接埠21的連線(資料連線還是會保留)。不設定的話當作300
。data_connection_timeout
:設定資料連線的逾時時間。不設定的話當作300
。hide_ids
:設定是某隱藏檔案的擁有者和群組。不設定的話當作NO
。若設為YES
,會將擁有者和群組以ftp
來顯示。pam_service_name
:設定要使用哪個PAM服務來驗證使用者。預設是vsftpd
。若沒有這個服務,就會使用Linux作業系統的使用者作為FTP的一般使用者。這個部份會和虛擬使用者登入有關,會在文章後面做介紹。
若vsftpd是以獨立運行的方式來啟動,還可以用以下的設定項目進行連線數量的限制:
max_clients
:設定最多同時處理幾組FTP連線。不設定的話表示沒有限制。max_per_ip
:設定同一IP最多同時允許幾組FTP連線,其實也就影響著同一個IP最多可以上傳和下載幾個檔案啦!不設定的話表示沒有限制。
chroot的設定
「chroot」為「change root directory」,可以讓使用者無法觸及到比根目錄還要更上層的檔案。
chroot_local_user
將chroot_local_user
項目設為YES
,可以將一般使用者的根目錄都設定為他們各自的家目錄。要注意的是,任何使用者(包括一般使用者和匿名使用者)對其根目錄都不能有寫入權限,所以還需要用以下設定調整所有一般使用者家目錄的權限。
所以要讓一般使用者透過FTP上傳檔案的話,只能夠在使用者家目錄中事先新增能讓該使用者寫入的子目錄才行。
chroot_list_enable
相較於chroot_local_user
設定項目是直接去修改「所有」一般使用者的根目錄為他們各自的家目錄,chroot_list_enable
項目則可以修改「指定某幾個」一般使用者的根目錄為他們各自的家目錄。指定的方式是透過一個獨立的chroot清單檔案,預設路徑為/etc/vsftpd.chroot_list
,可能需自行建立。
chroot清單檔案的撰寫方式如下:
user1,user2,user3
以上的chroot清單檔案,在chroot_list_enable = YES
且chroot_local_user
不是YES
時,user1
、user2
和user3
使用者的根目錄會被設定為他們自己的家目錄。若chroot_list_enable = YES
且chroot_local_user = YES
時,則除了user1
、user2
和user3
使用者以外,其它一般使用者的根目錄才會被設定為他們自己的家目錄。
當然,用chroot_list_enable
項目去修改使用者根目錄,也是要去注意根目錄的寫入權限,不能讓使用者自己擁有該目錄的寫入權限。
另外還有chroot_list_file
設定項目,可以修改chroot清單檔案的路徑。
虛擬使用者(Virtual User)
上面介紹的FTP登入方式共有實體使用者(Linux作業系統的使用者,即上面一直提到的一般使用者)和匿名使用者兩種,如果有特殊需求需要允許非Linux作業系統使用者的使用者也能夠實名登入FTP站台的話,那麼可以使用這小節介紹的方式來設定虛擬使用者。不過用了這個方式後,就不能再用原先的實體使用者來登入FTP站台了。
這個方式需要用到PAM(Linux Pluggable Authentication Modules),PAM的設定檔位於/etc/pam.d
目錄中,設定檔的格式如下:
其中,類型有以下幾種:
- account:提供帳號檢驗。像是使用者的密碼是否過期,使用者是否有被允許存取某項服務等。
- auth:提供使用者身份驗證。像是要求使用者輸入密碼,或是使用視網膜、指紋辨識週邊設備來驗證身份。
- password:提供使用者身分驗證的修訂功能。像是修改密碼。
- session:記錄使用者登入後到登出前的資訊。
驗證後要做的事有以下幾種:
- requisite:驗證失敗的話立刻回報。
- required:驗證失敗的話不立刻回報,會在其它模組都調用完畢後才回報。
- sufficient:驗證成功的話立刻回報。
- optional:只有在這個服務和類型僅使用一個模組時,驗證有無成功才是重要的。這個通常是拿來顯示訊息用的。
我們可以在/etc/pam.d
目錄中建立一個vsftpd
設定檔,檔案內容如下:
auth required pam_userdb.so db=/etc/vsftpd.vusers account required pam_userdb.so db=/etc/vsftpd.vusers session required pam_loginuid.so
上面的設定並沒有包含服務名稱,服務名稱即為設定檔檔名vsftpd
。這個PAM服務要使用/etc/vsftpd.vusers.db
檔案作為使用者帳密和身份驗證的資料庫,並且把登入識別碼記錄起來。在使用pam_userdb.so
的時候,檔案路徑不必加上.db
,它會自動加,不能自己加上。至於/etc/vsftpd.vusers.db
檔案是什麼,要怎麼產生,等等會介紹。先再執行以下指令來安裝db-util
套件吧!
然後用以下的方式設定vsftpd的主設定檔:
local_enable=YES guest_enable=YES virtual_use_local_privs=YES chroot_local_user=YES user_sub_token=$USER local_root=/home/vftp/$USER
上面有幾個是先前沒有介紹過的設定項目,如下:
- guest_enable:設定是否將一般使用者作為「訪客」,寄宿到某個使用者(以
guest_username
項目來設定,預設是ftp
)下。不設定的話表是否。換句話說,可以讓登入至FTP站台的一般使用者通通都當作是某個指定的使用者,方便進行權限的控管。 - virtual_use_local_privs:設定透過PAM驗證的虛擬使用者是否擁有一般使用者的權限。不設定的話就是只有匿名使用者的權限。
建立存放虛擬使用者家目錄的目錄/home/vftp
。可以使用以下指令:
後面的chown
指令其實並非必要,只是我們習慣把家目錄的擁有者和群組設為套用該家目錄的使用者以及其專屬群組。
用以下指令來建立虛擬使用者清單檔案,路徑可以放在/etc/vsftpd.vusers
:
因為這個檔案會包含密碼,所以只讓root
帳號有權限讀寫。
編輯虛擬使用者並產生使用者資料庫
編輯虛擬使用者清單檔案/etc/vsftpd.vusers
,單數行為使用者的帳號,雙數行為使用者的密碼,一組使用者帳號密碼會佔用連續的兩行。檔案內容的結構如下:
user1 password1 user2 password2 user3 password3
以上設定,第1組使用者的帳號為user1
,密碼為password1
,依此類推。
接著用以下指令來產生資料庫:
產生出來的資料庫檔案權限當然也是只讓root
帳號有權限讀寫。
若有新增虛擬使用者,要使用mkdir
指令新增虛擬使用者的家目錄。例如:
在SSL/TLS通道上建立FTP連線
由於FTP是採用未加密的明碼傳輸,因此在傳輸過程中若有遭有心人士擷取封包,很容易導致帳號密碼以及檔案文件外洩。如果要在網際網路中使用FTP,最好還是把FTP連線建立在SSL/TLS通道上,使其變成俗稱的FTPS。
首先執行以下指令產生自我簽署的SSL憑證。
私鑰會被放在/etc/ssl/private/ssl-cert-snakeoil.key
,證書會被放在/etc/ssl/certs/ssl-cert-snakeoil.pem
,有效期為10年。
如果您有大略瀏覽過vsftpd的主設定檔,會發現裡面已經有設定好rsa_cert_file
項目和rsa_private_key_file
項目了。我們要做的只是把ssl_enable
項目設為YES
即可啟用SSL/TLS通道。
另外,關於FTPS,還有以下幾個常用的設定項目可以調整:
allow_anon_ssl
:是否允許匿名使用者使用SSL/TLS通道。不設定的話是不允許。如果FTP站台只是提供給匿名使用者下載檔案的話,建議不要允許,節省系統資源。但如果匿名使用者可以上傳檔案的話,還是允許一下會比較好。force_anon_data_ssl
:是否強制讓匿名使用者使用SSL/TLS通道建立資料連線。不設定的話是不強制。設定策略同allow_anon_ssl
項目。allow_anon_ssl
項目必須要啟用才可以啟用這個項目。如果啟用這個項目,就不能直接給人FTP網址下載檔案。force_local_data_ssl
:是否強制讓一般使用者使用SSL/TLS通道建立資料連線。不設定的話是不強制。建議設為YES
,強制使用。force_local_logins_ssl
:是否強制讓一般使用者使用SSL/TLS通道進行登入(傳遞密碼)。不設定的話是YES
。建議設為YES
,強制使用。
套用vsftpd的新設定
若vsftpd是以獨立運行的方式來啟動,執行以下指令來重啟vsftpd:
若vsftpd是透過超級服務來啟動,在設定檔修改之後建立的FTP連線都會套用到新的設定。