最近研究如何在內網搭架FTP服務器,同時要保證外網(公網)能訪問的到。終成正果,但走了一些彎路,在此記下,以饗後人。服務器
FTP 使用 2 個端口,一個數據端口和一個命令端口(也叫作控制端口)。這兩個端口通常是21 (命令端口)和 20 (數據端口),固然你也能夠自定義。控制 Socket 用來傳送命令,數據 Socket 是用於傳送數據。每個 FTP 命令發送以後,FTP 服務器都會返回一個字符串,其中包括一個響應代碼和一些說明信息。其中的返回碼主要是用於判斷命令是否被成功執行了。操作系統
通常來講,客戶端有一個 Socket用來鏈接 FTP 服務器的相關端口,它負責 FTP 命令的發送和接收返回的響應信息。一些操做如「登陸」、「改變目錄」、「刪除文件」,依靠這個鏈接發送命令就可完成。.net
對於有數據傳輸的操做,主要是顯示目錄列表,上傳、下載文件,咱們須要依靠另外一個 Socket來完成。日誌
若是使用被動模式,一般服務器端會返回一個端口號。客戶端須要用另開一個 Socket 來鏈接這個端口,而後咱們可根據操做來發送命令,數據會經過新開的一個端口傳輸。blog
若是使用主動模式,一般客戶端會發送一個端口號給服務器端,並在這個端口監聽。服務器須要鏈接到客戶端開啓的這個數據端口,並進行數據的傳輸。教程
下面對 FTP 的主動模式和被動模式作一個簡單的介紹。ip
主動模式下,客戶端隨機打開一個大於1024 的端口向服務器的命令端口 P,即 21 端口,發起鏈接,同時開放N +1 端口監聽,並向服務器發出 「port N+1」 命令,由服務器從它本身的數據端口 (20) 主動鏈接到客戶端指定的數據端口 (N+1)。路由
FTP 的客戶端只是告訴服務器本身的端口號,讓服務器來鏈接客戶端指定的端口。對於客戶端的防火牆來講,這是從外部到內部的鏈接,可能會被阻塞。字符串
爲了解決服務器發起到客戶的鏈接問題,有了另外一種 FTP 鏈接方式,即被動方式。命令鏈接和數據鏈接都由客戶端發起,這樣就解決了從服務器到客戶端的數據端口的鏈接被防火牆過濾的問題。get
被動模式下,當開啓一個 FTP 鏈接時,客戶端打開兩個任意的本地端口 (N > 1024 和 N+1) 。
第一個端口鏈接服務器的 21 端口,提交 PASV 命令。而後,服務器會開啓一個任意的端口 (P > 1024 ),返回如「227 entering passive mode (127,0,0,1,4,18)」。 它返回了 227 開頭的信息,在括號中有以逗號隔開的六個數字,前四個指服務器的地址,最後兩個,將倒數第二個乘256 再加上最後一個數字,這就是 FTP 服務器開放的用來進行數據傳輸的端口。如獲得 227 entering passive mode(h1,h2,h3,h4,p1,p2),那麼端口號是 p1*256+p2,ip 地址爲h1.h2.h3.h4。這意味着在服務器上有一個端口被開放。客戶端收到命令取得端口號以後, 會經過 N+1 號端口鏈接服務器的端口 P,而後在兩個端口之間進行數據傳輸。
使用Serv-U搭架FTP服務器很簡單,網上教程也不少,再也不累述。我這裏只記錄下我遇到的問題。
FTP軟件
FTP軟件版本
FTP服務器
Windows XP
Serv-U
版本15.0.1.20
FTP客戶端
Windows XP
FileZilla
版本3.8.0
FTP服務器安裝在公司內網的電腦上,FTP客戶端在外網的電腦上(嚴格來講也是在另外一外局域網內)。
被動模式(PASV)下,有數據要傳輸時,服務器會打開一個數據端口(並處於監聽狀態),而後告知客戶端,客戶端鏈接這個數據端口發送數據。可是數據端口是隨機的,那麼服務器該如何將這些隨機數據端口映射到公網的路由器上呢???總不能讓內部網的一臺機器徹底暴露到公網上吧,雖然確實有這樣的方案(稱之爲DMZ主機),但這絕對是最愚蠢的選擇。
這就是我遇到的第一個彎路,折騰了好久才知道。雖然數據端口是隨機的,但Serv-U能夠指定隨機的範圍。打開Serv-U管理控制檯 > 管理服務器 > 服務器限制和設置 > 服務器設置 。在「設置」選項卡里找到「PASV端口範圍」,以下圖所示,在這裏就能夠指定隨見的範圍了。你只要把這些端口映射到路由器就能夠了。
圖表 1 PASV 端口範圍
固然別忘了,還有一個命令端口也得映射。
我遇到的第二個難纏的問題是,FileZilla客戶端獲取不到FTP服務器的目錄列表。日誌信息以下:
狀態: 正在鏈接 125.89.123.99:13000...
狀態: 鏈接創建,等待歡迎消息...
響應: 220 Serv-U FTP Server v15.0 ready...
命令: USER zhangsan
響應: 331 User name okay, need password.
命令: PASS ***
響應: 230 User logged in, proceed.
命令: CLNT FileZilla
響應: 200 Noted.
命令: OPTS UTF8 ON
響應: 200 OPTS UTF8 is set to ON.
命令: OPTS MLST type;size;modify;perm;
響應: 200 MLST OPTS Type;Size;Modify;Perm;
狀態: 已鏈接
狀態: 讀取目錄列表...
命令: PWD
響應: 257 "/" is current directory.
命令: TYPE I
響應: 200 Type set to I.
命令: PASV
響應: 227 Entering Passive Mode (100,100,100,100,50,203)
命令: MLSD
響應: 150 Opening BINARY mode data connection for MLSD.
錯誤: 鏈接超時
錯誤: 讀取目錄列表失敗
也是通過一陣折騰,最後忽然發現服務器對PASV指令的響應是:227Entering Passive Mode (100,100,100,100,50,203),這裏100.100.100.100是FTP服務器在內網IP,客戶端天然鏈接不上。打開Serv-U管理控制檯 > 你自定義的域名 > 域詳細信息 > 監聽器 > 編輯 ,在PASV IP地址或域名中設置公網IP便可。 以下圖所示。
FTP服務器至少須要兩個端口:命令端口和數據端口。命令端口是固定的,而數據端口是隨機的。隨機的端口如何映射到公網?Serv-U能夠設置PASV端口範圍,隨機也只是在設定的範圍內隨機。另外須要設置PASV IP地址,否者服務器響應客戶端的PASV 命令時,會把服務器在內網中的IP地址告知客戶端,這個地址對應客戶端來講是鏈接不上的。