摘要: 做爲很是古老的協議(1971年首次提出,1980年首次應用),FTP在目前依然佔有一席之地,可是因爲目前IT業發展的很是迅猛,它和如今的基礎架構產生了一些水土不服,本文旨在經過平常常見的案例,來介紹如何在阿里雲上搭建FTP Server和FTP Client。安全
做爲很是古老的協議(1971年首次提出,1980年首次應用),FTP在目前依然佔有一席之地,可是因爲目前IT業發展的很是迅猛,它和如今的基礎架構產生了一些水土不服,本文旨在經過平常常見的案例,來介紹如何在阿里雲上搭建FTP Server和FTP Client。服務器
本文先從FTP的協議分析,重點闡述了其中控制通道的兩種鏈接模式,進而說明在阿里雲上搭建FTP服務器可能遇到的問題,如被動模式下服務器公網IP沒法獲取、主動模式下沒法鏈接等狀況。網絡
在FTP協議中,一般有兩個通道:控制通道和數據通道,前者用來傳輸控制命令,如協議握手、得到當前目錄等操做,而數據通道顧名思義,就是用來傳輸文件數據之用,另外ls命令的結果一般也會經過數據通道來傳輸。架構
而被動模式和主動模式是針對如何創建數據通道而言的,這裏的主動、被動是站在服務器的角度上描述的,他們的差異簡單來講就是數據通道的TCP鏈接創建是由誰發起的,主動模式下服務器主動向客戶端創建數據通道,而被動模式下,服務器是等待客戶端來鏈接的。網站
這兩個模式你們聽到比較多的應該是被動模式,一般網上的文章都會建議客戶端使用被動模式來鏈接,下面簡單來講明一下二者的差異。this
主動模式的詳細操做能夠參考我以前寫的一篇文章,這裏節選部分信息:阿里雲
如下是一次完整的交互,客戶端爲47.x.x.224,服務端爲112.x.x.7。spa
對他的分析能夠參考以後的一張交互圖,須要重點說明的是交互圖中標紅的一行,這一行能夠理解爲數據通道的實際體現(抓包中倒數第4個包,因爲我只過濾了FTP協議的包,TCP的控制包沒有顯示出來,這個包其實是創建了一個新的TCP流來傳輸的),在這以前PORT命令是由客戶端發出的,這一條報文爲code
PORT 47,x.x,224,39,16
其中前四個數字爲十進制的IP地址,在主動模式下爲客戶端的IP地址,最後兩個數字爲端口,因爲端口須要兩個字節表示,因此在這裏的計算方式爲39x256+16=10000,那麼這一條報文的意思就是告訴服務器,「我計劃使用10000端口做爲監聽的端口,個人IP地址是47.x.x.224,你能夠來鏈接我了進行數據傳輸了」。orm
而被動模式最顯著地差異就是在於如何創建數據通道,主動模式下是服務端去鏈接客戶端傳輸數據,而被動模式下,是客戶端去發起鏈接,向服務器創建鏈接。
如下是一次被動模式下的交互,客戶端爲30.x.x.85,服務端爲47.x.x.255。
能夠看出最大的區別在於紅框中的命令,這一次從PORT改成PASV,以後服務器回覆一條被動模式的信息,其中一樣是6個數字:IP地址+端口號(端口號的計算方法和主動模式中同樣),只是這一次換作服務器告訴客戶端,「你如今能夠鏈接個人47.x.x.255的47185端口了」。
這裏特別提示一下,從下面的抓包截圖中能夠看出服務器回覆的PASV響應中IP地址並非上面提到的47.x.x.255,而是一個私網地址172.x.x.241,緣由咱們會在# 專有網絡ECS內部署FTP Server #這一節中提到。
爲什麼會同時存在被動模式和主動模式呢?在互聯網的初期,因爲各個終端使用的都是標準的公網IP地址,彼此時間能夠互相通訊,互相可見,因此在發起TCP鏈接時,無所謂是哪一方先發起。但隨着互聯網的高速發展,人們發現IP地址已經不夠用了,進而誕生了NAT技術,這就在通訊的雙方之間插入了一箇中間人,在NAT設備以後的終端對於對方是不可見的,因此只能由它來發起鏈接。
因此爲了迎合NAT技術,FTP協議裏就出現了被動模式,並且因爲目前大部分FTP客戶端都是在NAT設備以後,因此絕大多數狀況下只能使用被動模式(固然在一些特殊的架構裏主動模式仍是有必定的用武之處,本文最後一節將會說起)
目前阿里雲ECS的網絡類型有兩種:經典網絡與專有網絡。對於經典網絡的ECS來講,系統內有兩張網卡:eth0和eth1,eth0爲內網網卡,eth1爲外網網卡。在系統內內網和外網的IP地址是靜態寫在配置文件裏的,系統內能夠直接看到。而專有網絡的ECS系統內只有一張網卡eth0,全部的流量都由這張網卡出入,系統內部沒法看到ECS自身的公網IP/彈性公網IP。
這就直接致使了一個問題:因爲目前的網絡環境下大部分客戶端都會使用被動模式來鏈接,可是被動模式下服務器須要告訴客戶端鏈接的IP地址,而專有網絡下的ECS沒法直接看到外網IP,那麼就致使FTP Server將本身的私網IP告訴了客戶端,客戶端收到了一個私網IP天然就沒法進行鏈接。而list、文件傳輸都須要走FTP協議的數據通道,因此最終致使了專有網絡下搭建的FTP Server沒法讓客戶端正常的傳輸數據。
解決辦法也很簡單:主動告知FTP Server程序系統的外網地址,因爲市面上FTP Server衆多,各家的設置方式不盡相同,如下說明幾個常見的FTP服務器的設置方法:
在vsftpd的配置文件中,加入如下兩行,其中替換爲ECS的彈性公網地址:
listen_ipv6=NO pasv_address=<EIP>
打開IIS,選擇服務器(注意不要選擇「網站」下的ftp站點),打開右側的「防火牆支持」,在「防火牆的外部IP地址」其中填入ECS的彈性公網地址便可。
打開管理控制檯,依次選擇「域」-》[對應的域]-》「域詳細信息」-》「監聽器」-》21端口的監聽器,點擊「編輯」,將ECS的彈性公網地址填入彈出的對話框中
在撰寫本文時,我發現一些客戶端彷佛已經提供了智能化的規避方案,如lftp提供如下參數,當出現相似的問題時會嘗試使用控制通道的服務器IP地址進行數據通道的鏈接。
ftp:fix-pasv-address (boolean) if true, lftp will try to correct address returned by server for PASV command in case when server address is in public network and PASV returns an address from a private network. In this case lftp would substitute server address instead of the one returned by PASV command, port number would not be changed. Default is true.
另外,FileZilla也默認開啓了修正被動模式下數據通道IP地址的功能:
阿里雲上的安全組至關於一個方向牆,相似iptables或Windows防火牆,能夠根據協議、源/目的IP、源/目的端口來實現特定流量的放行、攔截。在# 被動模式和主動模式 #一節中咱們已經提到了FTP除了21端口之外,根據不一樣的模式在數據通道下還會使用到特定的端口,因此須要在ECS的安全組中放行。
關於FTP兩種模式下的報文交互,前文已經作了闡述,但還未說明程序是如何選擇端口的,下面簡單說明一下:
- | 控制通道 | 數據通道 |
---|---|---|
客戶端 | 主動鏈接服務器,隨機選擇本地源端口 | 主動鏈接服務器,隨機選擇本地源端口 |
服務端 | 被動接受客戶端鏈接,本地默認監聽21端口 | 被動接受客戶端鏈接,本地隨機監聽端口 |
注:被動模式下服務端數據通道監聽的端口理論上能夠經過FTP程序的配置文件修改
- | 控制通道 | 數據通道 |
---|---|---|
客戶端 | 主動鏈接服務器,隨機選擇本地源端口 | 等待服務器的連接,本地監聽一個隨機的端口(注) |
服務端 | 被動接受客戶端鏈接,本地默認監聽21端口 | 主動連接客戶端,隨機選擇本地源端口 |
注:主動模式下客戶端數據通道監聽的端口理論上能夠經過FTP程序的配置文件修改
那麼能夠得出在ECS上部署FTP Server,若對於安全組有嚴格的進出限制,那麼須要放行:
這裏依然以常見的FTP程序爲例:
pasv_enable=YES pasv_min_port=10000 pasv_max_port=10020
前文提到在一些特定的場景下,確實只能使用主動模式,好比說IDC和銀行側相連,銀行出於安全考慮僅容許21端口入方向的流量,其他的端口都是封禁的,那麼就沒法使用被動模式,只能退而求其次使用主動模式。那麼此時對於客戶端的要求能夠總結爲下列幾點:
關於第2、3、四點,其實和被動模式下PASV命令的響應相似,都須要在程序中做相應的配置才行,但因爲這個場景下這個需求確實比較小衆,我只收集了少許的客戶端配置方法,其餘的客戶端配置方法請和程序的提供商尋求技術支持。
ftp:passive-mode (boolean) sets passive FTP mode. This can be useful if you are behind a firewall or a dumb masquerading router. In passive mode lftp uses PASV command, not the PORT command which is used in active mode. In passive mode lftp itself makes the data connection to the server; in active mode the server connects to lftp for data transfer. Passive mode is the default. ftp:port-ipv4 (ipv4 address) specifies an IPv4 address to send with PORT command. Default is empty which means to send the address of local end of control connection. ftp:port-range (from-to) allowed port range for active mode. Format is min-max, or `full' or `any' to indicate any port. Default is `full'.