在通過FTP進行文件操作之前,需完成以下任務:
須知:使用FTP協議存在安全風險,建議使用SFTP V2、SCP或FTPS方式進行文件操作。
通過FTP進行文件操作的配置流程如表1所示。
表1 通過FTP進行文件操作的配置流程
序號 | 配置任務名稱 | 配置任務說明 | 配置流程說明 |
1 | 配置FTP服務器功能及參數 | 包括FTP服務器的使能及參數配置:端口號、源地址、超時斷連時間。 | 序號1、2、3之間沒有嚴格的配置順序。 |
2 | 配置FTP本地用戶 | 包括配置本地用戶的服務類型、用戶級別及FTP用戶的授權目錄等。 | |
3 | (可選)配置FTP訪問控制 | 包括配置ACL規則及FTP基本訪問控制列表,提高FTP訪問的安全性。 | |
4 | 用戶通過FTP訪問設備 | 從終端通過FTP訪問設備。 | - |
表2 缺省配置
參數 | 缺省值 |
FTP服務器功能 | 關閉 |
端口號 | 21 |
FTP用戶 | 沒有創建本地用戶 |
配置FTP服務器功能及參數
表3 配置FTP服務器功能及參數
操作步驟 | 命令 | 說明 |
進入系統視圖 | system-view | - |
(可選)指定FTP服務器端口號 | ftp [ ipv6 ] server port port-number | 缺省情況下,FTP服務器端口號是21。 如果配置了新的端口號,FTP服務器端先斷開當前已經建立的所有FTP連接,然后使用新的端口號開始嘗試連接。這樣可以有效防止攻擊者對FTP服務標準端口的訪問。 |
指定FTP服務器的源地址 |
| 缺省情況下,未指定FTP服務器的源地址。 配置了服務器的源地址后,登錄服務器時,所輸入的服務器地址必須與該命令中配置的一致,否則無法成功登錄。 |
使能FTP服務器 | ftp [ ipv6 ] server enable | 缺省情況下,設備的FTP服務器功能是關閉的。 |
(可選)配置FTP連接空閑時間 | ftp [ ipv6 ] timeout minutes | 缺省情況下,連接空閑時間為10分鐘。 在設定的時間內,如果FTP連接始終處于空閑狀態時,系統將自動斷開FTP連接。 |
(可選)設置FTP服務器支持的最大會話數 | ftp [ ipv6 ] server max-sessions max-sessions-number | 缺省情況下,FTP服務器支持的最大會話數是5。 |
如果變更端口號前FTP服務已經啟動,則不能變更成功。需執行undo ftp [ ipv6 ] server命令關閉FTP服務,再進行端口號變更。
當客戶端與設備之間的文件操作結束后,請執行undo ftp [ ipv6 ] server命令,及時關閉FTP服務器功能,從而保證設備的安全。
配置FTP本地用戶
當用戶通過FTP進行文件操作時,需要在作為FTP服務器的設備上配置本地用戶名及口令、指定用戶的服務類型以及可以訪問的目錄,否則用戶將無法通過FTP訪問設備。
表4 配置FTP本地用戶
操作步驟 | 命令 | 說明 |
進入系統視圖 | system-view | - |
進入AAA視圖 | aaa | - |
配置本地用戶名和密碼 | local-user user-name password irreversible-cipher password | - |
配置本地用戶級別 | local-user user-name privilege level level | 說明: 必須將用戶級別配置在3級或3級以上,否則FTP連接將無法成功。 |
配置本地用戶的服務類型為FTP | local-user user-name service-type ftp | 缺省情況下,本地用戶可以使用所有的接入類型。 |
配置FTP用戶的授權目錄 | local-user user-name ftp-directory directory | 缺省情況下,本地用戶的FTP目錄為空。 當有多個FTP用戶且有相同的授權目錄時,可以執行set default ftp-directory directory命令,為FTP用戶配置缺省工作目錄。此時,不需要通過local-user user-name ftp-directory directory命令為每個用戶配置授權目錄。 |
配置本地用戶的FTP權限 | local-user user-name ftp-privilege [ directoryfilename ] { read | write | execute }* | 缺省情況下,本地用戶的FTP權限為讀、寫和執行權限。 |
(可選)配置FTP訪問控制
ACL是一系列有順序的規則組的集合,這些規則根據數據包的源地址、目的地址、端口號等來描述。ACL通過規則對數據包進行分類,這些規則應用到路由設備,路由設備根據這些規則判斷哪些數據包可以接收,哪些數據包需要拒絕。
用戶可以配置FTP訪問控制列表,實現只允許指定的客戶端登錄到設備,以提高安全性。
ACL規則:
表5 (可選)配置FTP訪問控制
操作步驟 | 命令 | 說明 |
進入系統視圖 | system-view | - |
進入ACL視圖 | acl [ number ] acl-number | - |
配置ACL規則 | rule [ rule-id ] { deny | permit } [ source { source-address source-wildcard | any } | fragment | logging | time-range time-name | { vpn-instance vpn-instance-name | public } ] * | - |
退回到系統視圖 | quit | - |
配置FTP基本訪問控制列表 | ftp [ ipv6 ] acl acl-number | - |
用戶通過FTP訪問設備
從終端通過FTP訪問設備,可以選擇使用Windows命令行提示符或第三方軟件。此處以Windows命令行提示符為例進行配置。
C:\Documents and Settings\Administrator> ftp 192.168.150.208
連接到 192.168.150.208。
220 FTP service ready.
用戶(192.168.150.208:(none)):huawei
331 Password required for huawei.
密碼:
230 User logged in.
ftp>
通過FTP命令進行文件操作
用戶訪問FTP服務器后,可以通過FTP命令進行文件操作,包括目錄操作、文件操作、配置文件傳輸方式、查看FTP命令在線幫助等。
說明:用戶的操作權限受限于服務器上對該用戶的權限設置。由于文件系統對根目錄下的文件個數有限制,當根目錄中文件個數大于50個時,繼續在根目錄中創建文件可能會失敗。
以下各操作沒有嚴格順序,可根據需求選擇一種或多種操作項目。
表6 通過FTP命令進行文件操作
操作項目 | 命令 | 說明 |
改變服務器上的工作路徑 | cd remote-directory | - |
改變服務器的工作路徑到上一級目錄 | cdup | - |
顯示服務器工作路徑 | pwd | - |
顯示或者改變客戶端的工作路徑 | lcd [ local-directory ] | 與pwd不同的是,lcd命令執行后顯示的是客戶端的本地工作路徑,而pwd顯示的則是遠端服務器的工作路徑。 |
在服務器上創建目錄 | mkdir remote-directory | 創建的目錄可以為字母和數字等的組合,但不可以為<、>、?、\、:等特殊字符。 |
在服務器上刪除目錄 | rmdir remote-directory | - |
顯示服務器上指定目錄或文件的信息 | dir/ls [ remote-filename [ local-filename ] ] |
|
刪除服務器上指定文件 | delete remote-filename | - |
上傳單個或多個文件 | put local-filename [ remote-filename ] 或 mput local-filenames |
|
下載單個或多個文件 | get remote-filename [ local-filename ] 或 mget remote-filenames |
|
配置傳輸文件的數據類型為ASCII模式或二進制模式 | ascii 或 binary | 二選一
|
配置文件傳輸方式為被動方式或主動方式 | passive 或 undo passive | 二選一 缺省情況下,數據傳輸方式是主動方式。 |
查看FTP命令的在線幫助 | remotehelp [ command ] | - |
使能系統的提示功能 | prompt | 缺省情況下,不使能信息提示。 |
打開verbose開關 | verbose | 如果打開verbose開關,將顯示所有FTP響應,包括FTP協議信息,以及FTP服務器返回的詳細信息。 |
(可選)更改登錄用戶
設備可以在不退出FTP客戶端視圖的情況下,以其他的用戶名登錄到FTP服務器。所建立的FTP連接,與執行ftp命令建立的FTP連接完全相同。
操作步驟 | 命令 | 說明 |
FTP客戶端視圖下,更改當前的登錄用戶 | user user-name [ password ] | 更改當前的登錄用戶后,原用戶與服務器的連接將斷開。 |
斷開與FTP服務器的連接
用戶可以在FTP客戶端視圖中選擇不同的命令斷開與FTP服務器的連接。
操作步驟 | 命令 | 說明 |
終止與服務器的連接,并退回到用戶視圖 | bye 或 quit | 二選一。 |
終止與服務器的連接,并退回到FTP客戶端視圖 | close 或 disconnect |
本次是2020年在生產環境遇到的問題手稿記錄,解決的問題是 ftp 操作導致大量的【TIME_WAIT】,現整理發出,希望幫助到有需要的人。
這個問題是在生產環境出現的,由于測試環境數據量小,程序很快運行完成,ftp 連接能被快速釋放,所以一直沒出現這個問題。
運維反饋,在 ftp 服務器監控到大量的連接【TIME_WAIT】,經查是一些 .net 程序導致的,如下前面三個都是部署了 .net 程序的服務器:
后面的是部署在 docker 容器中的 java 程序,數據還比較正常。
這些程序用的工具類可能是同一個(或者大同小異),所以批量出現了。
由于測試環境沒有重現這個問題,那么要解決這個問題需要在測試環境重現一下,好對癥下藥。
程序偽代碼邏輯主要如下:
void Start()
{
foreach (int item in list)
{
...
DownloadFile(...,path);
...
UploadPdf(...);
}
}
byte[] DownloadFile(...,string path)
{
var ftpUtil=new FtpUtil("10.10.60.16", "ftp", "123");
return ftpUtil.DownloadFile(...,path);
}
int UploadPdf(...,byte[] buffer)
{
var ftpUtil=new FtpUtil("10.10.60.16", "ftp", "123");
ftpUtil.UploadFile(..., buffer);
}
由上可看出代碼是有缺陷的,首先一點,由于 ftp 對象初始化都是一樣的,沒必要每處理一次就 new 一個 FtpUtil 對象實例,這意味著每次都會建立一個新的FTP連接,這樣做可能會導致連接池溢出或者頻繁地創建和關閉連接,影響性能并增加TIME_WAIT連接的數量。
第一個優化點:將FtpUtil實例創建移到循環外部,以便在整個循環過程中重用同一個實例,從而減少連接建立和關閉的次數。
程序涉及到 ftp 操作是先下載文件,然后上傳文件,問題應該是出現在 ftp 工具類中實現下載和上傳的兩個方法中。
編寫了一個單元測試項目用來重現此問題,就是模擬取一定量的訂單實現上面的下載和上傳邏輯,當只實現下載的時候問題沒出現,加了上傳邏輯才出現問題,說明上次方法有問題。
基本信息:
上傳過程中發現:
本次設置了100次,運行完成后統計發現產生了100次 連接:
當程序關閉后一兩分鐘后終于被釋放(公共的 ftp 服務器其它程序也會用):
問題終于復現了。
這到底啥原因呢?
要了解原因,首先要了解 TIME_WAIT 是什么意思?
TIME_WAIT 表示的是客戶端在操作 ftp 后進入的等待狀態。
那為什么會出現大量的 TIME_WAIT 呢?
經查代碼發現 FtpWebRequest 類有個屬性【KeepAlive】,指定在請求完成之后是否關閉到 FTP 服務器的控制連接,源碼解釋如下:
//
// 摘要:
// 獲取或設置一個 System.Boolean 值,該值指定在請求完成之后是否關閉到 FTP 服務器的控制連接。
//
// 返回結果:
// 如果不應銷毀到服務器的連接,則為 true;否則為 false。默認值為 true。
//
// 異常:
// T:System.InvalidOperationException:
// 對于一個已在進行的請求為此屬性指定了一個新值。
public bool KeepAlive { get; set; }
默認是 true,但是在上傳方法中設置的是 false,則表示客戶端在請求完成之后要關閉 FTP 服務器的控制連接,但是由于服務端是在收到客戶端發送關閉連接命令之后才會去主動關閉連接,由于有大批量的請求,所以造成服務器上比較容易出現大量的 TIME_WAIT 狀態的連接,特別是并發量較大時更易出現。
如果不設置這個屬性,那么默認是 true,整個程序生命周期中只有一個連接,請求完成之后不會關閉,一直會處于 ESTABLISHED 狀態,直到程序結束才會被釋放,如: