FTP协议

FTP 为什么还在用?一篇读懂它的工作原理

开篇:一个让你抓狂的场景

你写了一个 FTP 客户端,在公司内网测试一切正常。部署到客户环境后,文件传不成了——能登录,能列目录,但每次一传文件就卡死。

查了半天才发现:客户开了防火墙,而你的 FTP 用的是主动模式

这就是 FTP 协议最让人头疼的地方:它用了两条独立的 TCP 连接,而这两条连接的建立方式还分两种模式。不搞清楚这一点,踩坑是迟早的事。

读完这篇文章,你会彻底理解 FTP 的双通道设计、主动/被动模式的区别,以及如何在实际项目中避坑。


TL;DR

  • FTP 使用两条 TCP 连接:21 端口传命令(控制连接),数据端口传文件(数据连接)
  • 主动模式:服务器主动连接客户端的数据端口 → 容易被客户端防火墙拦截
  • 被动模式:客户端主动连接服务器的数据端口 → 对 NAT/防火墙更友好,现代网络首选
  • 抓包时找不到数据传在哪?去看 PASVPORT 命令的响应,端口号藏在里面

一、什么是 FTP

FTP(File Transfer Protocol,文件传输协议)是 Internet 上最经典的文件传输协议,用于在主机间双向传输文件。

默认使用 TCP 的 20 和 21 两个端口:

端口 用途
21 控制连接 —— 发送命令和接收响应
20(或协商端口) 数据连接 —— 传输文件内容

具体是否使用 20 端口作为数据端口,取决于 FTP 使用的传输模式:

  • 主动模式:服务器数据端口默认使用 20
  • 被动模式:端口由服务器和客户端协商决定

二、工作模式(核心章节)

FTP 支持两种工作模式:主动模式(PORT)被动模式(PASV)。两者的控制连接建立过程完全一致,区别在于数据连接由谁发起

2.1 一表看清区别

主动模式(PORT) 被动模式(PASV)
数据连接发起方 服务器 → 客户端 客户端 → 服务器
服务器数据端口 默认 20 随机端口(协商决定)
客户端数据端口 随机端口(客户端告知服务器) 随机端口
防火墙友好度 差(客户端需开放入站端口) 好(客户端发起出站连接)
适用场景 无防火墙的内网 有 NAT/防火墙的互联网环境
标识命令 PORT PASV

2.2 被动模式流程(PASV)

sequenceDiagram participant C as FTP 客户端 participant S as FTP 服务器 :21 Note over C,S: === 建立控制连接 === C->>S: TCP SYN (随机端口N → 21) S-->>C: 220 Service Ready C->>S: USER anonymous S-->>C: 230 Login OK C->>S: PASS xxx S-->>C: 230 Login OK Note over C,S: === 请求数据传输 === C->>S: PASV S-->>C: 227 Entering Passive Mode (IP, p1, p2) Note right of C: 数据端口 = p1*256 + p2 Note over C,S: === 建立数据连接 === C->>S: TCP SYN (随机端口M → 协商端口) S-->>C: 连接建立 Note over C,S: === 传输文件 === C->>S: RETR file.txt S-->>C: 150 Opening data connection S-->>C: 文件数据... S-->>C: 226 Transfer Complete

文字步骤简述:

  1. 客户端随机端口 N(>1024)连接服务器 21 端口,建立控制连接
  2. 完成用户认证(USER / PASS)
  3. 客户端发送 PASV 命令,服务器返回 227 响应,携带 IP 和端口号(port = p1×256 + p2
  4. 客户端用新随机端口连接服务器返回的数据端口,建立数据连接
  5. 数据传输完成后,数据连接关闭,控制连接保留

2.3 主动模式流程(PORT)

sequenceDiagram participant C as FTP 客户端 participant S as FTP 服务器 :21 Note over C,S: === 建立控制连接 === C->>S: TCP SYN (随机端口N → 21) S-->>C: 220 Service Ready C->>S: USER anonymous S-->>C: 230 Login OK Note over C,S: === 请求数据传输 === C->>S: PORT h1,h2,h3,h4,p1,p2 Note left of C: 客户端告知自己的 IP 和端口 S-->>C: 200 PORT OK Note over C,S: === 建立数据连接(服务器主动发起)=== S->>C: TCP SYN (20 → 客户端指定端口) C-->>S: 连接建立 Note over C,S: === 传输文件 === C->>S: RETR file.txt S-->>C: 150 Opening data connection S-->>C: 文件数据... S-->>C: 226 Transfer Complete

文字步骤简述:

  1. 控制连接建立和认证流程与被动模式相同
  2. 客户端通过控制连接发送 PORT 命令,告知服务器自己的 IP 和监听端口
  3. 服务器从 20 端口主动向客户端指定端口发起数据连接
  4. 数据传输完成后,数据连接关闭

主动模式的核心问题:如果客户端在 NAT 或防火墙后面,服务器无法主动连入,数据传输就会失败。


三、数据传输

3.1 数据结构

FTP 支持三种文件结构(使用 STRU 命令指定):

结构 说明
文件结构(默认) 文件被视为连续的字节流,无内部结构
记录结构 文件由连续记录组成,用于文本文件(TYPE ASCII / EBCDIC)
页结构 用于不连续文件(如随机存取文件),每页传输附带页头信息

3.2 传输模式

模式 特点 文件结束标识
流模式 以字节流传输,最简单 关闭连接表示结束
块模式 数据以带头的块传输 FTP 编码标识
压缩模式 支持数据压缩,有控制信息 FTP 编码标识

流模式下传输多文件时,TCP 的 TIME_WAIT 可能导致端口无法立即复用。如果有多文件传输需求,可以考虑使用块模式或压缩模式,它们不需要关闭连接来标识文件结束。

3.3 数据连接管理要点

  • 所有 FTP 实现必须支持默认数据端口,只有客户端可以使用非默认端口
  • 客户端可通过 PORT 命令指定非默认用户端口,也可通过 PASV 要求服务器指定非默认端口
  • 服务器在以下情况会关闭数据连接:传输完成、收到 ABOR 命令、端口设定变更、控制连接关闭、不可恢复错误

四、FTP 命令速查

4.1 常用命令

命令 全称 用途
USER User 用户名认证
PASS Password 密码认证
PASV Passive 进入被动模式
PORT Port 指定主动模式的数据端口
RETR Retrieve 下载文件
STOR Store 上传文件
LIST List 列出目录内容
CWD Change Working Directory 切换工作目录
QUIT Quit 断开连接
ABOR Abort 中断当前传输
TYPE Type 设置传输格式(A=ASCII, I=Binary)
PWD Print Working Directory 显示当前目录

4.2 完整命令参考

点击展开完整命令列表

访问控制命令:

命令 用途
USER 用户名认证
PASS 密码认证
ACCT 账户信息(部分站点需要)
CWD 改变工作目录
CDUP 返回上层目录
SMNT 装载不同的文件系统结构
REIN 重新初始化(保留控制连接,重置所有参数)
QUIT 注销并关闭控制连接

传输参数命令:

命令 用途
PORT 指定主动模式数据端口
PASV 请求被动模式
TYPE 设置表示类型(ASCII / EBCDIC / Image / Local)
STRU 设置文件结构(File / Record / Page)
MODE 设置传输模式(Stream / Block / Compressed)

服务命令:

命令 用途
RETR 下载文件
STOR 上传文件(覆盖)
STOU 唯一保存(不覆盖已有文件)
APPE 追加内容到文件末尾
ALLO 预分配存储空间
REST 断点续传标记
RNFR / RNTO 重命名文件(从/到)
ABOR 放弃当前传输
DELE 删除文件
RMD 删除目录
MKD 新建目录
PWD 打印当前工作目录
LIST 列出目录详细信息
NLST 列出文件名列表
SITE 站点特定服务
SYST 获取服务器操作系统类型
STAT 获取状态信息
HELP 帮助
NOOP 空操作(保活)

五、FTP 响应码

FTP 响应码为三位数字,每位有特定含义:

第一位:状态类型

状态码 含义 说明
1xx 预备状态 命令已接受,等待下一个命令
2xx 完成状态 命令成功完成
3xx 中间状态 命令已接受,等待进一步信息
4xx 暂时拒绝 临时性错误,可重试
5xx 永久拒绝 命令不被接受,不要重复请求

区分 4xx5xx 的规则:在相同状态下不加修改重复请求,是否还有可能成功。

第二位:响应类别

类别码 类别 含义
x0x 语法 命令不存在、未实现或多余
x1x 信息 对状态或帮助请求的响应
x2x 连接 关于控制/数据连接的响应
x3x 认证 登录过程和账户相关的响应
x4x 未使用 保留
x5x 文件系统 请求传输时的文件系统状态

常见响应码速查

含义
220 服务就绪
221 服务关闭控制连接
226 关闭数据连接,请求操作成功
227 进入被动模式(含 IP 和端口)
230 用户登录成功
331 用户名 OK,需要密码
425 无法打开数据连接
426 连接关闭,传输中止
530 未登录

六、抓包实战分析

6.1 被动模式抓包

环境:服务器 192.168.106.9,客户端 192.168.106.7

被动模式抓包1

被动模式抓包2

Step-by-step 分析:

步骤 方向 关键动作 关注点
1 客户端 → 服务器:21 TCP 三次握手 控制连接建立
2 服务器:21 → 客户端 220 服务就绪 服务器已准备
3 客户端 → 服务器:21 AUTH TLS / AUTH SSL 鉴权尝试(非 SFTP 故跳过)
4 客户端 → 服务器:21 USER anonymous 匿名登录
5 服务器:21 → 客户端 230 登录成功
6 客户端 → 服务器:21 TYPE A 设置为 ASCII 模式
7 服务器:21 → 客户端 200 设置成功
8 客户端 → 服务器:21 PASV 请求被动模式
9 服务器:21 → 客户端 227 Entering Passive Mode (192,168,106,9,4,15) 端口 = 4×256+15 = 1039
10 客户端 → 服务器:1039 TCP 三次握手 数据连接建立
11 客户端 → 服务器:21 RETR 123test.txt 请求下载文件
12 服务器:1039 → 客户端 文件数据 数据传输进行中
13 服务器:21 → 客户端 226 Transfer Complete 传输完成,数据连接关闭

6.2 主动模式抓包

主动模式抓包

主动模式与被动模式的关键区别:在 PORT 命令中,客户端将自身 IP 和监听端口告知服务器,由服务器端 20 端口主动发起数据连接。如果客户端在防火墙/NAT 后面,这条入站 SYN 会被拦截——这就是主动模式最常见的故障原因。


七、常见踩坑与排错指南

坑 1:主动模式被防火墙拦截

项目 说明
现象 能登录、能列目录,但传输文件时卡住或超时
原因 客户端在 NAT/防火墙后面,服务器无法主动连接客户端的数据端口
根因 使用的是主动模式(PORT),数据连接方向是 服务器→客户端
解决 客户端改用被动模式(发送 PASV 而非 PORT

坑 2:被动模式端口范围未开放

项目 说明
现象 切换被动模式后仍失败,或部分文件传输失败
原因 服务器防火墙只开放了 21 端口,PASV 协商出的随机数据端口被拦截
解决 在服务器端配置 PASV 端口范围(如 pasv_min_port=30000, pasv_max_port=30100),并在防火墙放行该范围

坑 3:FTP over TLS 被防火墙静默丢包

项目 说明
现象 明文 FTP 正常,启用 FTPS(FTP over TLS)后无法传输
原因 防火墙/IPS 对加密 FTP 控制连接做深度包检测失败,直接丢包或中断连接
解决 尝试将控制连接端口从 21 改为非标准端口;或确认防火墙支持 FTPS 并已配置放行

排错 Checklist


写在最后

FTP 诞生于 1971 年,早于 TCP/IP 协议栈,也早于防火墙和 NAT 这些现代网络基础设施。它的双通道设计在当年是优雅的,在今天就变成了麻烦。

但只要理解了主动/被动模式这一核心概念,FTP 依然是简单可靠的。下次遇到 FTP 问题,记得先问自己一个问题:数据连接是谁连谁?


参考资料:RFC 959 - File Transfer Protocol

posted @ 2022-07-26 14:58  北小北  阅读(1011)  评论(0)    收藏  举报