窺探FTP通信細節

前幾天,老張寫了兩篇關於FTP的文章:

給大家介紹了FTP的通信機制,然後又帶大家寫了一個玩具版的FTP服務端代碼。

今天繼續給大家帶來FTP系列的第三篇《窺探FTP通信細節》,通過抓包FTP的通信,將FTP的扒的底褲都不剩。


 


 

環境準備:

  • FTP客戶端測試腳本:依然選擇Python自帶的Ftplib來編寫測試腳本

  • Wireshark:一個網絡層的抓包工具

  • 一臺主機:用於運行FTP客戶端腳本和Wireshark。ip爲192.168.16.1

  • 一臺Linux虛擬機:運行Vsftpd作爲FTP服務端。ip爲192.168.16.129

  • FTP服務器的模式:選擇主動模式,使用Binary模式傳輸數據。

 注:爲什麼不用老張的玩具版?使用成熟通用的Vsftpd是爲了能夠更好的幫助大家理解,避免不必要的歧義。

 

OK,請各位繫好安全帶,馬上開車了!

 

1. 連接FTP服務器,建立命令通道通道

import ftplibftp = ftplib.FTP()ftp.connect("192.168.16.129", 21)此時使用Wireshark抓包,可以看到:

經過TCP的三次握手,命令通道建立。此時FTP服務器會向客戶端發送一條220狀態碼的消息,表示命令通道已建立。但是注意,此時還沒有登錄鑑權。

 

2. 客戶端發送賬號密碼

ftp.connect("192.168.16.129", 21)ftp.login("root", "root")  # 此處密碼並非正式密碼,抓包時老張也機智的把密碼抹去了此時報文消息如下:

可以看到賬號和密碼是通過兩條消息分別發送的。

3. 客戶端設置本次連接使用主動模式:

ftp.set_pasv(False)

此行爲完全是客戶端本地行爲,沒有同服務器之間進行信息交換。

4. 將本地文件上傳至服務器:

# 將本地文件上傳至服務器with open("client", 'rb') as f:    ftp.storbinary("STOR upload_from_client", f, 1024)雖然看起來只有一個STOR命令,但是此時卻是客戶端和服務器之間信息交換最繁忙的時候,爲了能夠講清楚,老張將整個過程拆解了一下。

4.1 傳輸上傳命令:

 

首先,客戶端通過命令通道通知服務端,本次數據傳輸將使用Binary模式。

然後,客戶端將自己爲數據通道準備的host及port發送給服務器。

注:關於端口號port的傳輸格式,可以參考上一篇的代碼實現。

最後,客戶端才發送上傳命令,通知服務器文件需要保存在默認文件夾,使用“upload_from_client”作爲文件名。

4.2 建立數據通道,傳遞數據:

 

可以看到,數據通道是需要時纔會建立,並不是一開始就建立好的,並且在數據傳輸完成之後立刻關閉。

還有另一個細節,主動模式下,服務器在收到上傳命令後,響應上傳命令和建立數據通道是同步進行的,這一點是我們的單線程玩具版不能比擬的。

4.3 服務器通知客戶端,上傳完成:

 

5. 下載服務器文件至本地:

# 下載服務器文件with open("download_from_server", "wb") as f:    ftp.retrbinary("RETR server", f.write)同上傳流程類似,這裏我們繼續拆解。

5.1 傳輸下載命令:

到這裏有沒有發現,其實下載和上傳的流程是幾乎一模一樣的。

5.2 建立數據通道,傳遞數據:

必須指出的是,每次客戶端建立數據通道使用的端口號並不是固定不變的。

5.3 服務器通知客戶端,下載完成:

一旦數據傳輸完成,服務器依然會發送一條消息通知客戶端。


6. 程序退出,命令通道關閉:

 


 

以上就是FTP的通信細節,不知道各位同學看完有沒有一絲疑惑?沒錯,老張之前也給大家強調過FTP協議是明文傳輸,你所有的祕密都不是祕密!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章