ftp 真的是一个很老很老的协议。
怀念在学校用 ftp 下载电影的日子[1]。。。
问题描述
在测试某个 ftp 服务端实现时发现 ftp 客户端在设置 Active 数据传输模式时,即使服务端防火墙阻止 20 端口的流量,数据传输仍然能够正常完成,而这与我所了解的 ftp 的行为并不一致。
测试代码如下:
#! /usr/bin/env python
from ftplib import FTP
ftp = FTP()
ftp.connect('host-or-ip', 21, 15)
ftp.login('user', 'password')
print(ftp.getwelcome())
print(ftp.pwd())
# ftp.retrlines('LIST')
def stor(fp):
def _stor(data):
fp.write(data)
return _stor
# Active mode
ftp.set_pasv(False)
# Passive mode
# ftp.set_pasv(True)
fn = 'test.zip'
with open(fn, 'wb') as fp:
ftp.retrbinary('RETR ' + fn, stor(fp))
print('retr \'{}\' ok, quit'.format(fn))
ftp.quit()
问题分析
报文交互截图如下,其中 192.168.5.4 是 ftp 客户端,192.168.9.131 是 ftp 服务端:
显然,从 Active 模式的截图可以看到,服务端在主动连接客户端建立数据传输通道时,服务端并没有 bind 到 20 端口,从而防火墙就无法阻止 20 端口的流量了。
而根据 RFC[5] 的描述:
3.2. ESTABLISHING DATA CONNECTIONS
The mechanics of transferring data consists of setting up the data
connection to the appropriate ports and choosing the parameters
for transfer. Both the user and the server-DTPs have a default
data port. The user-process default data port is the same as the
control connection port (i.e., U). The server-process default
data port is the port adjacent to the control connection port
(i.e., L-1).
3.3. DATA CONNECTION MANAGEMENT
Default Data Connection Ports: All FTP implementations must
support use of the default data connection ports, and only the
User-PI may initiate the use of non-default ports.
在 Active 模式下,服务端应该是需要 bind 到 20 (L - 1 = 21 - 1 = 20) 端口的。
参考资料
[1] lftp使用
http://www.cppblog.com/runsisi/articles/77572.html
[2] Active FTP vs. Passive FTP, a Definitive Explanation
http://slacksite.com/other/ftp.html
[3] What is the difference between active and passive FTP?
https://stackoverflow.com/a/27820711
[4] Why does FTP passive mode use a range of ephemeral ports as opposed to a single well known port?
[5] FILE TRANSFER PROTOCOL (FTP)
https://tools.ietf.org/html/rfc959
最后修改于 2019-02-11