本文将针对 ftp 系统共介绍 6 部分,分别是 ftp 协议 (双重连接:控制和数据连接),ftp 的主动和被动模式 (区别 / 使用场景 / 实现过程),ftp 传输方式 / 文件类型 / 数据结构,ftp 控制连接命令和 ftp 响应码,ftp 客户端服务端的编程注意事项,以及最后的抓包分析.
1.ftp 协议介绍
ftp 协议 是工作于 TCP/IP 模型的应用层,基于的传输协议是 TCP.FTP 客户端和服务端之间的连接是可靠的和双重的,为数据的传输提供保证.之所以是双重连接,因为 FTP 是一个会话交互系统,客户每次调用 FTP,都会建立控制连接的会话,以发送控制命令.客户每发起一次请求,会跟服务端建立一个数据连接的会话,以传送实际的数据文件.当数据文件传输结束,关闭数据连接,还可以通过控制连接进行发送命令.
2. ftp 主动模式和被动模式
FTP 协议之 wikipedia ftp 是 client-server 架构模型,client 和 server 之间建立单独的控制连接和数据连接.FTP 可以运行在 active 主动模式或 passive 被动模式,运行的模式决定 ftp 如何建立数据连接.
主动模式和被动模式的区别是什么?
二者在控制连接过程都是一样的,在数据连接时不一样:主动模式下是服务端主动连接客户端以建立数据连接;被动模式下是服务端被动的,由客户端连接服务端以建立数据连接.
主动模式和被动模式的使用场景
1) 当 ftp 服务器能力比较弱时,ftp 客户端可以采用被动模式.
2) ftp 服务器不支持主动模式或被动模式,那么 ftp 客户端只能采用被动或主动模式.
3) 针对客户端 firewall 场景,当 ftp 服务端主动连接客户端的某个数据端口被防火墙 firewall 过滤的问题,ftp 客户端可以采用被动模式.
4) 针对 NAT 场景,当服务端主动连接客户端的某个端口时,发送 port 命令中包含的端口和 ip 地址,需要转换为内部的 ip 和端口而不是公共的 ip 和端口号,ftp 客户端可以采用被动模式.另外一种方法是需要一个 application-level gateway 来为 NAT 进行转换为内部的 IP 和端口,此时也可以使用主动模式.
被动模式和主动模式的实现过程
FTP 客户端和服务端建立连接
FTP 服务端运行 (FTP 服务开启),服务器上有 "主服务进程" 运行,即服务器发布一个服务,比如端口是 21,用户名和密码为 11/22.
被动模式下,FTP 交互的过程如下:
1) ftp 客户端先启动一个 socket 控制进程,打开客户端的某个端口,访问 ftp 服务端的 21 端口.客户端用 TCP 和指定主机上的 ftp 服务器之间建立控制连接.
2) ftp 服务端主进程收到请求后,派生出来一个服务端控制进程,和客户端控制进程之间建立控制连接,开始会话.
3) ftp 客户端和 ftp 服务端之间通过各自的控制进程进行用户名和密码校验等操作.
4) 当 ftp 客户端要发起数据文件传输时,ftp 客户端控制进程向服务端控制进程发起 pasv 命令.
5) ftp 服务端控制进程收到 pasv 请求后,派生出来一个数据传输进程,并将端口号告知客户端控制进程,返回 227 entering passive mode (h1,h2,h3,h4,p1,p2),其中端口号是 p1*256+p2,ip 地址为 h1.h2.h3.h4.
6) ftp 客户端控制进程收到响应后,派生出来一个客户端数据传输进程,随机产生一个客户端数据传输端口,连接服务端的数据传输端口号,然后进行数据文件传输.
7) 当数据传输完毕,服务端数据传输进程返回传输完毕,数据连接通道会关闭,保留控制连接通道.
8) 如果此时没有其他文件传输,控制通道也会相继关闭.
主动模式下,FTP 交互的过程如下:
除了被动模式的 4),5),6) 步骤不一样外,其余都一样.
4) 当 ftp 客户端要发起数据文件传输时,客户端派生出一个数据传输进程,并通过客户端控制进程将数据连接的 port 告知服务端控制进程.
5) 当 ftp 服务端收到请求后,派生出一个服务端数据传输进程,产生一个服务端端口号,然后根据请求中 ftp 客户端数据传输进程序端口号建立数据传输连接.
6) ftp 客户端收到服务端的响应后,进行数据文件的传输.
问题反思:
1) 每传输一个文件会建立一个数据传输连接还是共用一个数据连接?- 看第 6 部分抓包分析可知答案.
3.ftp 传输方式 / 文件类型 / 数据结构
文件类型: NVT ASCII 码,EBCDIC(要求客户端服务端都是 EBCDIC 系统),图像文件 (数据发送呈现连续的比特流),local 模式 (服务端和客户端之间协商).
数据结构:文件结构 (字节流),记录结构 (文本文件),页结构 (文件被划分为页,随机读取或顺序存放).
传输方式:流模式 (数据以字节流形式传送,适用于记录结构和文件结构),块模式 (以块的形式传送,块带有自己的头部,头字节包括 16 位计数域和 8 位描述子代码),压缩模式.
4.ftp 控制命令和响应码
控制连接:NVT ASCII
数据连接:文件类型,数据结构,传输方式
ftp 控制命令和响应都是以 nvt ascii 形式传送,每行结尾都要 CR,LF 对.
常用命令 (从 ftp 登录到退出过程):
USER 系统登录用户名
PASS 系统登录的密码
TYPE 文件类型 (A=ASCII,E=EBCDIC,I=binary)
STRU 数据结构 (F=file,R=record,P=Page)
MODE 传输模式
PASV 等待数据连接的请求
PORT
IP 地址和两个字节的端口 id
CWD 改变服务器上的工作目录
LIST 列出显示的文件和目录
PWD 显示当前工作目录
RETR 从 server 下载文件到 client
REST 由特定偏移量重启文件传递
STOR 上传文件到服务器
STOU 上传文件到服务器 (不覆盖同名文件)
ACCT 系统优先级
DELETE 删除服务器上指定文件
RMD 在服务器上删除指定目录
MKD 在服务器上建立指定目录
QUIT 从 ftp 服务器退出登录
常用响应码 (从 ftp 登录到退出过程):
332 需要账号名 331 用户名有效,需要密码
230 登录成功 530 登录失败
200 成功
227 进入被动模式 (发送 IP 和端口号)
220 服务器准备就绪 421 关闭服务器
225 数据连接打开 425 不能打开数据连接
226 数据连接关闭
452 磁盘空间不足 552 超过分配的存储空间
426 结束连接
500 无效命令 504 无效命令参数
501 错误参数 502 命令未执行
125 数据连接已打开,在短时间内开始传输
120 在短时间内服务器准备就绪
250 完成的文件行为
257 当前的路径名 550 不可用的文件
553 不允许的文件名 551 不知道的页类型
5. ftp 客户端和服务端的编程步骤
Socket 客户端编程主要步骤如下:
1) socket() 创建一个 Socket(控制和数据)
2) connect() 与服务器连接 (控制和数据)
3) listen() 监听 (主动模式下)
4) write() 和 read() 进行会话
5) close() 关闭 Socket(控制和数据)
Socket 服务器端编程主要步骤如下:
1) socket() 创建一个 Socket(控制和数据)
2) bind()
3) listen() 监听
4) accept() 接收连接的请求
5) write() 和 read() 进行会话
6) close() 关闭 Socket(控制和数据)
6. 抓包分析 (被动和主动模式)
被动模式抓包分析 (ftp 客户端默认为被动)
ftp 客户端:192.168.0.102
ftp 服务端:192.168.0.100,端口 2121,用户名和密码都是 ftp.
ftp 控制连接
首先控制连接在 TCP 三次握手结束后,ftp 服务器响应 220 表明服务端已经准备就绪 (ftp 客户端控制连接的端口号 62463,服务端控制连接的端口号 2121).
然后是客户端通过控制连接发送 auth tls 和 ssl 鉴权命令,服务端响应 502 表明未执行命令 (因不是 sftp,所以没有执行 ssl 鉴权命令).
客户端通过控制连接发送 USER ftp 命令,服务端响应 331(表明用户有效,需要密码).客户端继续发送 PASS ftp 命令,服务端 230 表明 ftp 登录成功.
客户端通过控制连接发送 SYST 命令获取服务器操作系统,服务端返回 UNIX type:L8.
客户端通过控制连接发送 FEAT 命令,服务端返回 211(系统状态回复)表明 ftp 服务端支持扩展命令 (FEAT 命令是用来请求 FTP 服务器列出它的所有的扩展命令与扩展功能的,属于主动模式命令,被动模式慎用,如果服务端不支持呢!) 客户端没有发任何信息,服务端回复 UTF8 MDTM MEMT 211END.
客户端通过控制连接发送 OPTS UTF8 on 命令,服务端响应 200(表明 OPTS 成功)(OPTS 为特性选择项,解决服务端目录乱码问题).
客户端通过控制连接发送 PWD 命令,服务端响应 257 显示当前路径名称 "/".
客户端通过控制连接发送 TYPE I 命令,服务端响应 200(表明客户端和服务端以二进制传输设置成功).
客户端通过控制连接发送 PASV 命令,服务端响应 227(表面服务端进入被动模式),ip 和端口号 53093.
ftp 数据连接
客户端通过控制连接发送 LIST 命令,客户端和服务端之间的数据连接在进行三次握手后 (端口号 62464 和 53093),服务端控制连接响应 150(文件 OK,短时间内将关闭数据连接)(表明服务端开启二进制传输文件列表模式).然后服务端通过数据连接 (端口 53093 向 62464).文件传输成功后服务端通过控制连接响应 226 表明数据连接短时间内传输完毕并关闭.
客户端通过控制连接发送 MDTM 命令,服务端响应 213 20171211135455(服务端返回文件最终修改时间)(213 是文件系统回复).
cwd 切换目录
客户端通过控制连接发送 CWD backup 命令,服务端响应 250(完成目录切换行为).客户端 ftp 要求显示当前路径,发送 PWD,服务端响应 257 响应当前路径名.
客户端通过控制连接发起 pasv 命令,服务端响应 227(服务端数据连接的端口号为 51785).客户端控制连接发送 list 命令,客户端和服务端又一次 TCP 三次握手建立数据连接 (端口号 62467 和 51785),服务端控制连接响应 150(短时间内开启数据连接) 开启二进制模式进行列表显示.服务端通过数据连接 51785 向客户端数据连接 62467 发送文件列表.
ftp 上传文件建立连接
客户端通过控制连接 (62470 和 62469) 发起 2 次 pasv 命令(网络有环路),服务端响应 2 次 227(服务端数据连接的端口号为 42131 - 对应客户端控制连接的 62470,服务端数据连接 58968 对应客户端控制连接 62469).
客户端通过数据连接 62470 向服务端控制连接 2121 发送 STOR ping.png.数据连接 62469 也向服务端控制连接 2121 发送 STOR ping2.png.客户端和服务端之间通过 TCP 三次握手建立 2 个数据连接 (62475-42131,62476-58968).然后开始文件传输.
ftp 上传图片
文件传输成功后,服务端控制连接 2121 分别向客户端控制连接 62470 和 62469 响应 150 数据传输 (数据连接短时间内开启).然后通过建立的 2 个数据连接进行传输数据,当传输完毕,服务端控制连接 2121 会分别向客户端控制连接 62470 和 62469 响应 226 数据传输完毕.
控制连接断开没有抓到包 (手工关闭 ftp,没有看到 quit 的命令).
主动模式抓包 (仅解介绍和被动模式不一样的地方)
ftp 客户端:192.168.0.102
ftp 服务端:192.168.0.101,端口 2121,用户名和密码都是 ftp.
ftp 客户端 (fileZilla) 设置为主动模式,如下
Ftp 客户端设置为主动模式
客户端通过控制连接 51321 向服务端控制连接 2121 发送 PORT 192.168.0.102,200,122 命令,服务端控制连接响应 200(进入主动模式).
ftp 主动模式
客户端通过控制连接发起 list 命令,服务端和客户端又一次 TCP 三次握手建立数据连接 (服务端数据连接 51436 和客户端数据连接 51322).服务端响应 150(短时间开启数据连接) 开启二进制传输文件列表.服务端通过数据连接进行传输文件列表.
来源: http://www.jianshu.com/p/05212313d0e2