FTP 是专门基于 TCP 的服务。
FTP 没有 UDP 组件。
FTP 是一种不寻常的服务,因为它使用两个端口,一个“数据”端口和一个“命令”端口(也称为控制端口)。
传统上,这些是用于命令端口的端口 21 和用于数据端口的端口 20。
然而,当我们发现根据模式的不同,数据端口并不总是在端口 20 上时,混乱就开始了。
主动FTP
在主动模式 FTP 中,客户端从一个随机的非特权端口(N > 1024)连接到 FTP 服务器的命令端口,端口 21.
然后,客户端开始侦听端口 N+1,并将 FTP 命令端口 N+1 发送到 FTP服务器。
然后,服务器将从其本地数据端口(端口 20)连接回客户端指定的数据端口。
从服务器端防火墙的角度来看,要支持主动模式 FTP,需要打开以下通信通道:
- 来自任何地方的 FTP 服务器的端口 21(客户端发起连接)
- FTP 服务器的端口 21 到端口 > 1024(服务器响应客户端的控制端口)
- FTP 服务器的端口 20 到端口 > 1024(服务器发起数据连接到客户端的数据端口)
- FTP 服务器的端口 20 从端口 > 1024(客户端发送 ACK 到服务器的数据端口)
拉出后,连接显示如下:
- 从客户端端口 1026 (Cmd) 到服务器端口 21 (Cmd)
- 从服务器端口 21 (Cmd) 到客户端端口 1026 (Cmd)
- 从服务器端口 20(数据)到客户端端口 1027(数据)
- 从客户端端口 1027(数据)到服务器端口 20(数据)
在步骤 1 中,客户端的命令端口联系服务器的命令端口并发送命令 PORT 1027.
然后服务器在步骤 2 中将 ACK 发送回客户端的命令端口。
在步骤 3 中,服务器在其本地数据端口上发起连接以客户端之前指定的数据端口。
最后,客户端发回一个 ACK,如步骤 4 所示。
主动模式 FTP 的主要问题实际上落在客户端。
FTP 客户端不会与服务器的数据端口建立实际连接——它只是告诉服务器它正在侦听哪个端口,然后服务器连接回客户端上的指定端口。
从客户端防火墙来看,这似乎是一个外部系统启动与内部客户端的连接——通常是被阻止的。
被动FTP
为了解决服务器发起到客户端的连接的问题,开发了一种不同的 FTP 连接方法。
在客户端使用命令告诉服务器它处于被动模式之后,这被称为被动模式或者 PASV。
在被动模式 FTP 中,客户端启动到服务器的两个连接,解决了防火墙过滤从服务器到客户端的传入数据端口连接的问题。
打开 FTP 连接时,客户端在本地打开两个随机的非特权端口(N > 1024 和 N+1)。
第一个端口在端口 21 上联系服务器,但是客户端将发出 PASV 命令,而不是随后发出 PORT 命令并允许服务器连接回其数据端口。
这样做的结果是服务器随后打开一个随机的非特权端口(P > 1024)并将 PORT P 命令发送回客户端。
然后客户端发起从N+1端口到服务器P端口的连接,传输数据。
从服务器端防火墙的角度来看,要支持被动模式 FTP,需要打开以下通信通道:
- 来自任何地方的 FTP 服务器的端口 21(客户端发起连接)
- FTP 服务器的端口 21 到端口 > 1024(服务器响应客户端的控制端口)
- FTP 服务器的端口 > 1024 来自任何地方(客户端向服务器指定的随机端口发起数据连接)
- FTP 服务器的端口 > 1024 到远程端口 > 1024(服务器将 ACK(和数据)发送到客户端的数据端口)
绘制时,被动模式 FTP 连接如下所示:
- 从客户端端口 1026 (Cmd) 到服务器端口 21 (Cmd)
- 从服务器端口 21 (Cmd) 到客户端端口 1026 (Cmd)
- 从客户端端口 1027(数据)到服务器端口 2024
- 从服务器端口 2024(Cmd)到客户端端口 1027(数据)
在步骤 1 中,客户端通过命令端口联系服务器并发出 PASV 命令。
然后服务器在步骤 2 中回复 PORT 2024,告诉客户端它正在侦听哪个端口以进行数据连接。
在步骤 3 中,客户端然后启动从其数据端口到指定服务器数据端口的数据连接。
最后,服务器在步骤 4 中将 ACK 发送回客户端的数据端口。
虽然被动模式 FTP 从客户端解决了许多问题,但它在服务器端打开了一系列问题。
最大的问题是需要允许任何远程连接到服务器上的高编号端口。
幸运的是,许多 FTP 守护程序,包括 solaris in.ftpd 守护程序,允许管理员指定 FTP 服务器将使用的端口范围。
有关详细信息,请参阅附录 1.
第二个问题涉及支持和故障排除支持(或者不支持)被动模式的客户端。
例如,Solaris ftp 守护程序随附的命令行 FTP 实用程序从 Solaris 9(从 sccs v1.20 开始)支持被动模式。
查看手册页 (in.ftpd),选项 -p。
随着万维网的广泛普及,许多人更喜欢将他们的网络浏览器用作 FTP 客户端。
大多数浏览器在访问 ftp:// URL 时仅支持被动模式。
这可能是好是坏,具体取决于服务器和防火墙配置为支持的内容。
主动 FTP 示例
下面是一个活动 FTP 会话的实际示例。
唯一改变的是服务器名称、IP 地址和用户名。
在此示例中,FTP 会话从 user01 (192.0.0.1)(一个运行标准 FTP 命令行客户端的solaris 机器)到 dest_serv (192.0.0.2)(一个运行 solaris[TM] 9 ftpd 的solaris 机器)发起。
调试 (-d) 标志与 FTP 客户端一起使用以显示幕后发生的事情。
斜体字是调试输出,显示发送到服务器的实际 FTP 命令以及从这些命令生成的响应。
关于这个对话框,有一些有趣的事情需要考虑。
请注意,当发出 PORT 命令时,它指定了客户端 (192.0.0.1) 系统上的端口,而不是服务器上的端口。
当我们使用被动 FTP 时,我们会看到相反的行为。
在我们讨论这个主题时,请快速说明一下 PORT 命令的格式。
正如我们在下面的示例中看到的那样,它被格式化为一系列由逗号分隔的六个数字。
前四个八位字节是 IP 地址,而后两个八位字节包含将用于数据连接的端口。
要找到实际端口,请将第五个八位字节乘以 256,然后将第六个八位字节添加到总数中。
因此,在下面的示例中,端口号是 ((256*188) + 231) 或者 48359.
使用 netstat 快速检查应该可以确认此信息。
$ ftp -d dest_serv Connected to dest_serv. 220 dest_serv FTP server ready. Name (dest_serv:boqueron): root ---> USER root 331 Password required for root. Password: ---> PASS XXXX 230 User root logged in. ---> SYST 215 UNIX Type: L8 Version: SUNOS Remote system type is UNIX. ---> TYPE I 200 Type set to I. Using binary mode to transfer files. ftp> ls ---> PORT 192,0,0,1,188,231 200 PORT command successful. ---> TYPE A 200 Type set to A. ---> NLST 150 Opening ASCII mode data connection for file list. TT_DB bin (...) var vol xfn 226 Transfer complete. 191 bytes received in 0.03 seconds (6.16 Kbytes/s) ---> TYPE I 200 Type set to I. ftp> quit ---> QUIT 221-You have transferred 0 bytes in 0 files. 221-Total traffic for this session was 599 bytes in 1 transfers. 221-Thank you for using the FTP service on dest_serv. 221 Goodbye. # netstat -a | grep 48359 dest_serv.ftp-data user01.48359 33580 0 49640 0 TIME_WAIT
被动 FTP 示例
下面是一个被动 FTP 会话的实际示例。
唯一改变的是服务器名称、IP 地址和用户名。
在本示例中,FTP 会话从 user01 (192.0.0.1)(一个运行标准 FTP 命令行客户端的 solaris 机器)到 dest_serv(192.0.0.2)(一个运行 solaris 9 ftpd 的 solaris 机器)发起。
调试 (-d) 标志与 FTP 客户端一起使用以显示幕后发生的事情。
斜体字是调试输出,显示发送到服务器的实际 FTP 命令以及从这些命令生成的响应。
正常的服务器输出以黑色显示,用户输入以粗体显示。
请注意本示例中 PORT 命令与活动 FTP 示例的不同之处。
在这里,我们看到在服务器 (192.0.0.2) 系统上打开了一个端口,而不是客户端。
请参阅上面“活动 FTP 示例”部分中有关 PORT 命令格式的讨论。
$ ftp -d dest_serv Connected to dest_serv. 220 dest_serv FTP server ready. Name (dest_serv:boqueron): root ---> USER root 331 Password required for root. Password: ---> PASS XXXX 230 User root logged in. ---> SYST 215 UNIX Type: L8 Version: SUNOS Remote system type is UNIX. ---> TYPE I 200 Type set to I. Using binary mode to transfer files. ftp> passive Passive mode on. ftp> ls ---> PASV 227 Entering Passive Mode (192,0,0,2,7,176) ---> TYPE A 200 Type set to A. ---> NLST 150 Opening ASCII mode data connection for file list. TT_DB bin cdrom (...) vol xfn 226 Transfer complete. 191 bytes received in 0.027 seconds (7.04 Kbytes/s) ---> TYPE I 200 Type set to I. ftp> quit ---> QUIT 221-You have transferred 0 bytes in 0 files. 221-Total traffic for this session was 599 bytes in 1 transfers. 221-Thank you for using the FTP service on dest_serv. 221 Goodbye.