FTP 协议那些事

来源:互联网 发布:淘宝举报假冒商品 编辑:程序博客网 时间:2024/06/14 18:30

目录

    • 目录
    • 主动模式与被动模式
    • 弱网络传输
      • 断点续传
      • 分块确认
    • 防火墙与代理

主动模式与被动模式

和 HTTP 不同的是,FTP 采用两条链路通信,一条链路只做控制,一条链路只做数据传输。控制链路传输控制命令,数据链路传输文件内容或命令的输出结果,控制链路 server 监听 well-known 端口(默认 21),数据链路端口使用视传输模式而定。

  • 被动模式(默认)

ftp_passive_mode

所谓被动模式,是指 server 端的数据连接是被动打开,即 server 监听某端口,client 连接该端口。对于这种模式,数据端口采用随机端口,server 通过控制链路告知 client 当前数据端口是多少。例如:

ftp> put /tmp/test.txt /0/test.txtlocal: /tmp/test.txt remote: /0/test.txt---> TYPE I200 Switching to Binary mode.---> PASV227 Entering Passive Mode (10,105,51,240,211,175)

server 会在 PASV 命令的 reply 中指明本次传输采用 54191(211*256+175) 端口进行数据传输。

  • 主动模式

ftp_active_mode

主动模式则刚好相反,即 server 连接 client 主动打开数据链路,且 server 使用的端口固定,默认为 20.

弱网络传输

笔者所在的一个项目中,要将游戏安装包从大陆传输到日本的 CDN 源站,出海网络质量无保障,时好时坏,经常遇到传输到一半就超时失败,超时之后用户又得重传。于是就有了“断点续传”的想法,FTP 协议里有两个命令能实现断点续传,一个是 REST(restart), 另一个是 APPE(append), 这里不详细展开。

断点续传

断点续传也就是超时之后获取已经上传的大小(SIZE 命令),重试未上传的部分。

但是,在 FTP 的设计里面,数据链路只能传数据,没有确认包,因为 send 不会超时(假设发送缓冲区没满),也就无法实现“超时重传”。因此,要实现“超时重传”,必须要有 receive. 在 FTP 的设计里面,客户端关闭数据连接,如果 server 收到了 FIN 包,server 会在控制连接上回复 226 Transfer complete. 响应,客户端收到该响应则表示 server 已收到 FIN 包,进一步说明,文件极有可能已经收到(之所以说是“极有可能”是因为有些包可能滞留在网络中,比 FIN 包晚到)。因此,就有了如下步骤

  • send file content on data connection
  • close data connection
  • receive reply on command connection
  • receive timed out
  • get remote file size
  • send file content again

分块确认

在网络质量比较差的情况下,发送一个 300M 的文件,可能 server 只收到了 100M, 但是客户端却要发送完整个文件才关闭数据连接,多余的 200M 只会让网络更拥堵。因此,为了提升传输效率,我们引入了“分块确认”的机制。整个过程如下:

  • send 1 block
  • close data connection
  • receive reply on command connection
  • receive timed out
  • get remote file size
  • send 1 block from offset “remote size”

防火墙与代理

笔者所在的项目中,有这样一种场景:文件从印尼、越南、泰国等地传到 Akamai CDN 源站。东南亚的网络基础设施大多比较差,Akamai 提供的 CDN 源站域名会解析到日本或美国,在有些时段,网络质量非常差。由于新加坡到日本、印尼等到新加坡的网络质量较好,考虑在新加坡搭建一台 proxy. 文件从印尼等传到新加坡,再从新加坡传到 Akamai CDN 源站。

在之前的实践中,通过端口转发的方式实现 HTTP 的代理效果较好,因此复用了端口转发的方式。

  • 被动模式
    由于被动模式 server 的数据端口不固定,因此,端口转发无法实现。

  • 主动模式
    主动模式是服务端主动连接客户端,因此要考虑防火墙的设置,由于 server 是一个域名,接入了很多 IP, 因此防火墙的设置是个问题。
    此外,client 处于 NAT 网络之中,开启的数据端口通过控制链路的控制消息传递,即通过应用层消息传递地址,而 NAT 不会处理应用层数据,因此,外网的 FTP server 接收到的 client 监听的数据传输地址是一个内网地址,FTP server 无法主动连接该地址(不过如果 client 所在的网络环境使用了应用层网关(ALG), 该内网地址会被替换成外网地址,这个问题会随之解决).

因此,端口转发行不通。于是尝试了使用 HAProxy 的 TCP 代理,但在传大文件时会出现控制链路断开的问题,抓包分析之后,发现 TCP 代理只代理了控制链路,数据传输依然是直连 real server. 原因很简单,因为数据端口是在控制链路的消息中给出,TCP 代理无法修改应用层的内容。因此,要想实现 FTP 代理,必须替换应用层消息。也即是说,FTP 代理无法用三层代理来实现,只能通过应用层代理来实现。

原创粉丝点击