ftp协议的正常工作需要两个TCP连接:命令端口、数据端口。 前者用来传输纯文本的命令交互,此连接在整个FTP会话周期中不中断; 后者用来传输二进制、文本等数据信息,只是在需要传输数据时,才会建立此连接,传输数据完毕就关闭,属于临时会话的性质。
1. 服务器在21端口监听。 客户端在本地随机端口(eg 1982)发起和服务器21端口的TCP 连接,建立TCP连接成功后 next 。
2. 服务器发送hello信息给客户端
3. 客户端分别 通过USER PASS命令输入正确的用户、口令登陆
4. 服务器认证通过后返回2xx 正确相应。
至此FTP会话层(按ISO7层的定义)已成功建立
5. 客户端发送 CDUP PWD CWD 等命令切换当前工作目录
6. 服务器响应请求,并在命令端口返回指令相应 eg: 2xx 5xx 4xx
至此客户端、服务端的交互均仅仅局限在命令端口进行,双方的交互只占用一个TCP连接。对于NAT 防火墙等都不会有什么特殊影响
所谓主动模式、被动模式是指在数据端口工作时 服务器的在TCP 传输层的动作模式 。
主动模式下:
1. 客户端首先要用PORT命令告诉服务器,准备传数据了,并告知它自己在本地哪个端口listen;
2. 服务端收到PORT后,返回2xx 正确响应
3. 客户端再通过STOR RETR LIST等告诉服务端 它想要的数据
4. 服务端收到后,服务端主动发起本地一个随机端口至客户端listen的端口的 TCP连接, 再将数据塞给客户端
5. 服务器塞数据完毕后,在命令端口中返回2xx 正确响应。
6. 工作结束,关闭4 中建立的临时TCP连接。 命令端口的连接仍然保持,服务端等待客户端命令
被动模式下:
1. 客户端首先要用PASV命令告诉服务器,准备传数据了
2. 服务端收到PASV后,在本地listen一个端口,并返回2xx 正确相应信息 + listen的端口
3. 客户端收到响应后,发送STOR RETR LIST 等告知服务端 它想要的数据
4. 服务端收到命令后,准备相关数据,完毕后发送150 响应
5. 客户端收到正确响应后,客户端主动发起一个本地随机端口至服务端listen的端口的 TCP连接, 然后服务器将数据在此TCP连接塞给客户端。
6. 服务端塞数据完毕后,在命令端口中返回2xx 正确响应。
7. 工作结束,关闭4 中建立的临时TCP连接。 命令端口的连接仍然保持,服务端等待客户端命令
另:PORT PASSIVE命令中携带的端口信息是这样的:192,168,0,1,55,66 。 前面4个 192 168 0 1 是ip地址,后面两个计算后代表端口号: 55*256 + 66 = 14146, 14146就是端口号了
简而言之就是:
主动模式下,服务器把活包干了。客户端想要数据时,就简单的开本地监听端口,坐等服务器将数据塞给客户端;
被动模式下,服务器比较懒,客户端想要数据时,得要请求服务器监听一个端口,然后客户端主动连接服务器才能得到想要的数据。
中国的ip地址资源太少,很多情况下ftp回话两端要经过层层NAT、网关、防火墙。 导致PORT PASV中的ip 信息不一定都是正确的。比如client的ip是192.168.0.107,其实它是通过NAT连接上网的,该NAT对外的internet地址是218.2.135.1,那么client 发送的PORT指令中携带的192,168,0,107,xx,yy 对于server是没有意义的。 所幸现在的NAT、防火墙一般都有FTP应用层感知能力,它能够截获ftp会话中的PORT PASSIVE, 自动将private的ip翻译成对外的正确的ip,并实时的在NAT上开放临时端口转发 。刚才的例子就会翻译成 218,2,135,1,xx,yy。 所以一般情况下,ftp还是能够正常工作的。
主动模式下,客户端的NAT、防火墙容易导致连接问题。比如PORT 后 NAT需要临时开转发端口,并改变TCP报文中PORT的内容,如果NAT不具备应用层解析能力或只能感知标准21端口的命令,都将容易导致传数据失败。 而且 主动模式下对于使用代理、ssl,会带来很多其它问题。
被动模式下,问题主要集中在服务端的网络。因为需要服务器开临时端口并listen,对其部署的Firewall 要求有动态开 forward 的能力,这可能带来一定的安全隐患。 但是,大部分情况下,服务端的网络管理员应该已经配置了对FTP的支持。 所以推荐:大部分情况下,还是使用被动模式比较好。