先簡單介紹下FTP的基礎知識
FTP的傳輸有兩種方式:ASCII、二進制。
FTP支持兩種模式:Standard (PORT方式,主動方式),Passive (PASV,被動方式)。
- 主動模式
FTP 客戶端首先和服務器的TCP 21端口建立連接,用來發送命令,客戶端需要接收數據的時候在這個通道上發送PORT命令。PORT命令包含了客戶端用什么端口接收數據。在傳送數據的時候,服務器端通過自己的TCP 20端口連接至客戶端的指定端口發送數據。FTP server必須和客戶端建立一個新的連接用來傳送數據。
- 被動模式
建立控制通道和Standard模式類似,但建立連接后發送Pasv命令。服務器收到Pasv命令后,打開一個臨時端口(端口號大於1023小於65535)並且通知客戶端在這個端口上傳送數據的請求,客戶端連接FTP服務器此端口,然后FTP服務器將通過這個端口傳送數據。
很多防火牆在設置的時候都是不允許接受外部發起的連接的,所以許多位於防火牆后或內網的FTP服務器不支持PASV模式,因為客戶端無法穿過防火牆打開FTP服務器的高端端口(例如防火牆只開放了20、21端口);而許多內網的客戶端不能用PORT模式登陸FTP服務器,因為從服務器的TCP 20無法和內部網絡的客戶端建立一個新的連接,造成無法工作。說白了就是取決於防火牆限制了客戶端還是服務器,如果雙方都關閉了防火牆那么這兩種模式應該都是可以的。
為什么要用SFTP或FTPS
當你在FTP服務器上收發文件的時候,你面臨兩個風險。第一個風險是在上載文件的時候是明文傳輸。第二個風險是,這些文件在你等待接收方下載的時候將停留在FTP服務器上。
FTPS和SFTP都使用非對稱算法(RSA,DSA),對稱算法(DES / 3DES,AES,Twhofish等)和密鑰交換算法的組合。對於驗證FTPS(或更准確地說,FTP下的SSL / TLS協議)使用X.509證書,而SFTP(SSH協議)使用SSH密鑰。
X.509證書包括公鑰和有關證書所有者的某些信息。此信息允許另一方驗證證書本身的完整性和證書所有者的真實性。驗證可以通過計算機和在一定程度上由人來完成。 X.509證書具有關聯的私鑰,出於安全原因,通常與證書分開存儲。
SSH密鑰只包含公鑰(相關的私鑰是單獨存儲的)。它不包含有關密鑰所有者的任何信息。 同樣也不包含允許可靠地驗證完整性和真實性的信息。 一些SSH軟件實現使用X.509證書進行身份驗證,但實際上它們不驗證整個證書鏈 - 只使用公鑰(這使得此類身份驗證不完整,類似於SSH密鑰身份驗證)。
FTPS介紹以及它的優缺點
FTPS也稱作“FTP-SSL”和“FTP-over-SSL”,SSL是一個在客戶機和具有SSL功能的服務器之間的安全連接中對數據進行加密和解密的協議。SL/TLS協議在傳輸層(TCP/IP)之上、但是在應用層之下工作的。因此,它可以很容易在諸如HTTP,Telnet,POP3,IMAP4,SMTP和FTP等應用層協議上實現。SSL安全擴展至少有兩種不同的初始化方法:顯式安全和隱式安全。
- 顯示安全:為了建立SSL連接,顯式安全要求FTP客戶端在和FTP服務器建立連接后發送一個特定的命令給FTP服務器。客戶端使用服務器的缺省端口。
- 隱式安全:當FTP客戶端連接到FTP服務器時,隱式安全將會自動和SSL連接一起開始運行。在隱式安全中服務器定義了一個特定的端口(TCP端口990)讓客戶端來和其建立安全連接。
優點:
- 有良好的標准背景,在操作方面具有嚴格的定義
- 只有一個連接(不需要DATA連接)
- 連接始終保持安全
- 統一的目錄列表格式
- 協議包括用於權限和屬性操作,文件鎖定和更多功能的操作
缺點:
- 通信是二進制的,可讀性差
- SSH密鑰更難以管理和驗證
- 標准將某些事物定義為可選或推薦的,這導致某些兼容性問題
- 沒有服務器到服務器副本以及遞歸目錄刪除操作
- 在VCL和.NET框架中不支持內置的SSH / SFTP
SFTP介紹以及它的優缺點
SFTP是Secure File Transfer Protocol的縮寫,安全文件傳送協議。可以為傳輸文件提供一種安全的加密方法。SFTP 與 FTP 有着幾乎一樣的語法和功能。SFTP 為 SSH的一部分。其實在SSH軟件包中,已經包含了一個叫作SFTP(Secure File Transfer Protocol)的安全文件傳輸子系統,SFTP本身沒有單獨的守護進程,它必須使用sshd守護進程(端口號默認是22)來完成相應的連接操作,所以從某種意義上來說,SFTP並不像一個服務器程序,而更像是一個客戶端程序。SFTP同樣是使用加密傳輸認證信息和傳輸的數據,所以,使用SFTP是非常安全的。但是,由於這種傳輸方式使用了加密/解密技術,所以傳輸效率比普通的FTP要低得多,如果您對網絡安全性要求更高時,可以使用SFTP代替FTP。
優點:
- 廣為人知並使用
- 通信可以由人閱讀和理解
- 提供了服務器到服務器文件傳輸的服務
- SSL / TLS具有良好的身份驗證機制(X.509證書功能)
- 在許多互聯網通信框架中都支持內置FTP與SSL / TLS。
缺點:
- 沒有統一的目錄列表格式
- 需要輔助數據通道,這使其難以在防火牆后使用
- 沒有為文件名定義標准字符集(編碼)
- 並非所有FTP服務器都支持SSL / TLS
- 沒有標准的方式來獲取和更改文件和目錄屬性
根據場景如何選擇?
通常,答案取決於您的目標和要求。 一般來說,SFTP在技術上優於FTPS。 當然,實現對兩個協議的支持是一個好主意,但是它們在概念,支持的命令和許多其他方面是不同的。
當您具有需要從個人設備(智能手機,PDA等)訪問的服務器或具有FTP支持但沒有SSH / SFTP客戶端的某些特定操作系統時,最好使用FTPS。 如果您正在構建自定義安全解決方案,SFTP可能是更好的選擇。
對於客戶端,需求由您計划連接的服務器定義。 當連接到Internet服務器時,SFTP更受歡迎,因為它默認由Linux和UNIX服務器支持。
對於私有主機到主機傳輸,您可以使用SFTP和FTPS。 對於FTPS,您需要搜索一個免費的FTPS客戶端和服務器軟件或購買商業許可證。 對於SFTP支持,您可以安裝OpenSSH軟件包,它提供免費的客戶端和服務器軟件。 對於商業用途,我們建議使用Bitvise SSH服務器。
[敲黑板、划重點] 如果您是軟件開發人員,並且需要在應用程序中實現文件傳輸功能,則您將搜索組件以執行該作業。
.NET 中,對.NET Framework中的FTPS有內置支持(請參閱FtpWebRequest類)。 但是這個類的功能受到嚴格限制,特別是在SSL / TLS控制方面。
.NET Framework不包括對SSH或SFTP的任何支持。
注意.NET內置語法僅支持顯式的FTP over SSL,一般FTP服務器隱式端口為990,而顯式端口是21,一定要勾選允許顯式加密訪問。
VCL 中,您可以選擇提供FTP功能的免費組件和庫。 當您向他們添加OpenSSL時,您可以免費獲取FTPS。 如果您不想處理OpenSSL DLL,您可以使用一個商業上可用的庫來支持SSL和FTPS。 再次提醒,沒有免費的SFTP組件可用於.NET。
Java 中,FTPS和SFTP客戶端存在幾個不受支持和錯誤。
以上參考原文: https://blog.csdn.net/shmilychan/article/details/51848850
以上參考原文: https://www.cnblogs.com/OLDMAN-LU/p/6428274.html
FTP文件上傳代碼展示:
FtpWebRequest reqFTP; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.KeepAlive = false; reqFTP.Method = WebRequestMethods.Ftp.UploadFile; reqFTP.UseBinary = true; reqFTP.ContentLength = fileInf.Length; int buffLength = 20480; byte[] buff = new byte[buffLength]; int contentLen; FileStream fs = fileInf.OpenRead(); Stream strm = null; strm = reqFTP.GetRequestStream(); while (contentLen != 0) { strm.Write(buff, 0, contentLen); contentLen = fs.Read(buff, 0, buffLength); }
FTPS文件上傳代碼展示:
//驗證服務器證書,舉例默認返回true public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } FtpWebRequest reqFTP; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.KeepAlive = false; reqFTP.Method = WebRequestMethods.Ftp.UploadFile; reqFTP.UseBinary = true; //相比FTP,SFTP要求支持SSL req.EnableSsl = true; //首次連接頒發證書 ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate); reqFTP.ContentLength = fileInf.Length; int buffLength = 20480; byte[] buff = new byte[buffLength]; int contentLen; FileStream fs = fileInf.OpenRead(); Stream strm = null; strm = reqFTP.GetRequestStream(); while (contentLen != 0) { strm.Write(buff, 0, contentLen); contentLen = fs.Read(buff, 0, buffLength); }
SFTP文件上傳代碼就不展示了,C#需借第三方DLL之手實現SSH,流這塊的處理都封裝起來了,推薦Renci.SshNet.dll。