问题
最近使用Docker搭建FTP后,客户端可以连接无法列出目录,无法上传。通常我们认为FTP占用端口21用于传输控制命令,20传输数据。而我的21、20端口都有映射、开放。
环境
- Docker (24.0.2, build cb74dfc)
- Apache FtpServer (1.0.0)
原因分析
FileZilla连接效果如下
对应FtpServer的日志如下
根据上面信息看到前面的控制命令都正常工作,直到FtpServer收到”MLSD”时,出现异常
MLSD:获取远程服务器上的文件和目录列表(Machine List Directory)
此时,连接为PASV(被动模式),FtpServer使用端口26037与客户端连接传输数据
而26037端口并未对外开放,我们以为的只有21、20,26037又是怎么来的,在哪里配置的呢?
原来FTP分为PORT(主动模式)和PASV(被动模式)
FTP主动模式和被动模式
以下内容来源于ChatGPT
主动模式
在主动模式中,客户端首先建立一个控制连接(Control Connection)到服务器的FTP控制端口(默认为21)。当需要进行数据传输时,客户端会随机选择一个高位端口(大于1023)作为数据端口,并将该端口号发送给服务器。服务器会通过控制连接告知客户端它将使用的数据端口(服务器端口)。然后,客户端会主动连接服务器的数据端口,以进行数据传输。
被动模式
在被动模式中,客户端首先建立一个控制连接到服务器的FTP控制端口(默认为21)。当需要进行数据传输时,服务器会随机选择一个高位端口(1024-65535)作为数据端口,并将该端口号发送给客户端。然后,客户端会通过控制连接告知服务器它将使用的数据端口(客户端端口)。服务器会主动连接客户端的数据端口,以进行数据传输。
主动模式和被动模式的区别在于数据连接的建立方式。在主动模式中,客户端主动连接服务器的数据端口,而在被动模式中,服务器主动连接客户端的数据端口。
使用主动模式时,客户端需要打开一个高位端口用于数据连接,这可能会导致防火墙或网络设备的配置问题。而使用被动模式时,服务器打开一个高位端口用于数据连接,这样更容易通过防火墙和网络设备。
需要注意的是,FTP协议已经有一些安全性和性能问题,因此在实际应用中,往往会使用更安全和高效的替代协议,如SFTP(SSH File Transfer Protocol)或FTPS(FTP over SSL/TLS)。
附图
解决问题
了解到FTP主动模式、被动模式后,我们选择的是修改被动模式,因为我们无法干涉客户端的环境,客户端随机端口被防火墙拦截,我们无法处理。但被动模式下1024-65535的端口范围太大,我们不希望FtpServer开放这么多端口,那如何自定义修改呢?
修改FtpServer被动模式端口
修改FtpServer的ftpd-typical.xml
修改后端口范围为12200-12202,再开放映射端口后,就可以正常工作了
Notice:
When the client wants to use a passive data connection, the server should provide the port to use.
By default, FtpServer will choose any available port. However this can be overridden using the configuration for the passive data connection.
When the server has used up all passive ports (one per client doing passive data transfer), the next clients will have to wait for an available port.
It is therefore advised to provide multiple passive ports.
是否需要根据并发来考虑端口范围呢?
其中tcpdump作用太大,得精研一下