FTP 实战与排错 — 抓包、lftp/curl 与被动模式故障
Wireshark 提取传输文件、ftp/lftp/curl/nmap 命令、vsftpd 配置与被动模式端口不通排查 / 应用层 / TCP 21/20 / RFC 959
这篇你能学到
- 用 Wireshark /
tcpdump抓 FTP:怎么把传输的文件直接从抓包里还原出来,以及怎么一眼看出227返回的 IP 是不是私网(被动模式最经典故障)。 - 用
nc、ftp、lftp、curl、nmap做手工连接、断点续传、探测匿名登录与 Bounce 漏洞。 - 一份可直接用的 vsftpd 配置(被动端口范围、
pasv_address、FTPS),以及"425 / 530 / 550 / 文件损坏"等经典故障的"结论先行"排错法。 - FTP / FTPS / SFTP / SCP / HTTP / TFTP 的对比表和 10 道高频面试题。
抓包观察
Wireshark 显示过滤式
| 目的 | 过滤表达式 |
|---|---|
| 控制连接上的命令与应答 | ftp |
| 数据连接上的文件内容 | ftp-data |
| 控制 + 数据一起看 | ftp || ftp-data |
| 只看客户端发出的命令 | ftp.request |
| 只看服务器应答 | ftp.response |
| 指定命令 | ftp.request.command == "RETR" |
| 上传/下载/列表 | ftp.request.command in {"RETR","STOR","LIST","NLST"} |
| 抓取明文密码(演示协议不安全) | ftp.request.command == "PASS" |
| 指定应答码 | ftp.response.code == 530 |
| 所有失败应答 | ftp.response.code >= 400 |
| 找被动模式端口 | ftp.response.code == 227 |
| 扩展被动模式 | ftp.response.code == 229 |
| 主动模式的 PORT 命令 | ftp.request.command == "PORT" |
| 数据连接建立失败 | ftp.response.code == 425 |
| 按端口过滤(含数据连接) | tcp.port == 21 || tcp.port == 20 |
| FTPS(TLS 起来后) | tls && tcp.port == 21;隐式 tcp.port == 990 |
典型字段说明
Wireshark 会自动关联控制连接与数据连接:解析到 227 应答后,它会把对应端口的流量自动标记为 ftp-data,无需手工 Decode As。
排查动作:
- 找到
220欢迎语确认服务器版本(ftp.response.arg),很多漏洞与版本强相关。 - 找
530判断是认证问题;找550判断是权限/路径问题;找425判断是数据连接问题。 - 找
227应答,记下它返回的 IP——若服务器在 NAT 后且未配置pasv_address,这里会返回一个私网 IP,客户端连不上,这是被动模式最经典的故障。 - 对任一
ftp-data包右键追踪流 → TCP 流→ 另存为原始数据,可直接把抓包中传输的文件还原出来(文件 → 导出对象 → FTP-DATA更方便)。这也直观说明了明文 FTP 的危险。
tcpdump
下面这组 tcpdump/tshark 命令用于抓控制连接文本、按主机抓被动模式流量、以及把命令应答抽成表格。
| |
常用命令 / 配置
手工敲 FTP(最能建立直觉)
最直白的方式:用 nc 连上 21 端口,一行行手敲命令,亲眼看到三位数字应答。这是理解 FTP 双连接最快的办法。
系统自带 ftp 客户端
系统自带的 ftp 客户端排错最常用 -d(打开调试打印所有命令应答)和 -p(强制被动)。
| |
lftp —— 生产环境推荐的强大客户端
lftp 支持断点续传、镜像目录、显式 FTPS,是日常运维最顺手的客户端。
| |
curl 操作 FTP
curl 一条命令就能列目录、下载、上传、续传、强制主动/被动、走 FTPS。
| |
探测与验证
下面这组用于验证端口通不通、探测匿名登录、检测 Bounce 漏洞、确认被动端口范围是否放行。
| |
vsftpd 服务端配置要点
这份 vsftpd 配置覆盖了关键点:关匿名、开 chroot、配被动端口范围与公网 pasv_address、开 FTPS。
| |
对应的防火墙规则:
| |
常见故障与排错
下面每条先给"结论",再看排查——结论先行:先判断是数据连接问题、登录问题、还是传输类型问题。
425 Failed to establish connection/425 Can't open data connection- 先记住结论:数据连接建不起来——主动模式下客户端在 NAT 后,或被动模式下服务器被动端口没在防火墙放行。
- 排查:先
passive切被动;服务端确认pasv_min_port/max_port已在防火墙与安全组放行;nmap -p 40000-40100验证。
能登录、能
pwd,但ls就卡住- 先记住结论:典型的数据连接问题——
LIST也需要单独的数据连接,不是控制连接的问题。 - 排查:同上。这是"控制通、数据不通"的最经典症状。
- 先记住结论:典型的数据连接问题——
227应答里是私网 IP,客户端连不上- 先记住结论:服务器在 NAT/云主机后,没配
pasv_address,把内网地址报给了客户端。 - 排查:抓包看
227内容;vsftpd 配pasv_address=公网IP;或改用EPSV(229 应答不含 IP)。
- 先记住结论:服务器在 NAT/云主机后,没配
530 Login incorrect- 先记住结论:登录失败——密码错、用户在黑名单、白名单没包含、或匿名被禁用。
- 排查:看
/var/log/vsftpd.log与/var/log/secure;确认 shell 在/etc/shells中。
500 OOPS: vsftpd: refusing to run with writable root inside chroot()- 先记住结论:开了
chroot_local_user但家目录可写,vsftpd 出于安全拒绝启动。 - 排查:加
allow_writeable_chroot=YES,或把家目录本身设为不可写、在其下建可写子目录。
- 先记住结论:开了
550 Permission denied / Failed to open file- 先记住结论:文件系统权限不足、SELinux 拦截、
write_enable=NO或磁盘配额满。 - 排查:
ls -l检查属主与权限;getenforce与ausearch -m avc;df -h。
- 先记住结论:文件系统权限不足、SELinux 拦截、
文件传完但打不开 / 大小不对
- 先记住结论:用了 ASCII 模式传二进制文件,CRLF 被转换导致损坏。
- 排查:传输前必须
binary/TYPE I;对比本地与远端SIZE、md5。
421 Service not available/ Timeout- 先记住结论:空闲超时被踢、
max_clients/max_per_ip达上限,或服务没启动。 - 排查:调
idle_session_timeout;客户端定期NOOP保活;ss -ltnp确认服务在听。
- 先记住结论:空闲超时被踢、
大文件传到一半断,且传完收不到 226
- 先记住结论:控制连接长时间空闲被 NAT 会话表或防火墙清除,传输结束后控制线已断。
- 排查:开启 TCP keepalive;缩短 NAT 会话超时;客户端启用 keepalive 选项。
FTPS 能登录但传文件失败
- 先记住结论:加密后防火墙 ALG 无法解析
227应答,不能自动放行数据端口。 - 排查:必须手工放行完整的被动端口范围;或关闭 ALG 后静态放行。
- 先记住结论:加密后防火墙 ALG 无法解析
FTPS 报
SSL connection reuse错误- 先记住结论:部分客户端不复用控制连接的 TLS 会话到数据连接。
- 排查:服务端设
require_ssl_reuse=NO。
匿名登录成功但看不到任何文件
- 先记住结论:匿名根目录为空,或权限不允许列目录。
- 排查:检查
anon_root指向与目录权限(需 r-x)。
Windows 资源管理器/浏览器打不开 FTP
- 先记住结论:浏览器已彻底移除 FTP 支持(Chrome 95+、Firefox 90+),不是服务器问题。
- 排查:改用 FileZilla、WinSCP、lftp 等专用客户端。
中文文件名乱码
- 先记住结论:服务端与客户端字符集不一致,或未启用 UTF-8。
- 排查:
FEAT查看是否支持UTF8;客户端OPTS UTF8 ON;lftp 设set ftp:charset gbk。
通用排查顺序:21 端口能否连通(nc -zv) → 能否登录(看 530) → pwd 能否成功(控制连接正常) → ls 是否卡住(定位到数据连接) → 切被动模式重试 → 抓包看 227 返回的 IP 与端口 → 验证该端口是否放行 → 传二进制前确认 TYPE I。
与其他协议对比
| 维度 | FTP | FTPS | SFTP | SCP | HTTP(S) | TFTP |
|---|---|---|---|---|---|---|
| 底层协议 | 自有(RFC 959) | FTP + TLS | SSH 子系统 | SSH | HTTP | 自有(RFC 1350) |
| 端口 | TCP 21 / 20 | 21(显式)/ 990(隐式) | TCP 22 | TCP 22 | 80 / 443 | UDP 69 |
| 连接数 | 2 条(控制+数据) | 2 条 | 1 条 | 1 条 | 1 条 | 无连接 |
| 加密 | ❌ 全明文 | ✅ TLS | ✅ SSH | ✅ SSH | HTTPS 才有 | ❌ |
| 身份认证 | 明文口令 | 口令 + 服务器证书 | 公钥 / 口令 / 键盘交互 | 同 SFTP | 多种 | 无 |
| 穿 NAT / 防火墙 | ❌ 很差(需 ALG) | ❌ 更差(ALG 失效) | ✅ 好 | ✅ 好 | ✅ 好 | 差 |
| 断点续传 | ✅ REST | ✅ | ✅ | ❌ | ✅ Range | ❌ |
| 目录操作 | ✅ 完整 | ✅ | ✅ | ❌ 仅传文件 | 有限(WebDAV 补足) | ❌ |
| 传输效率 | 高(裸流) | 略低(加密开销) | 中(SSH 加密+分包) | 中 | 高 | 低 |
| 部署难度 | 中(被动端口麻烦) | 高 | 低(有 SSH 即有 SFTP) | 低 | 低 | 极低 |
| 典型场景 | 遗留系统、内网 | 需保留 FTP 语义的合规场景 | 现代首选 | 快速单文件拷贝 | 公开分发、API | PXE 引导、设备固件 |
选型建议:新项目一律选 SFTP(有 SSH 就有它,单端口、全加密、无被动模式烦恼);公开下载分发用 HTTPS;只有对接遗留系统或有明确合规要求时才用 FTPS;任何情况下不要在公网跑裸 FTP。
速查表 / 常见面试题
核心数字速查
| 项目 | 值 |
|---|---|
| 控制连接端口 | TCP 21 |
| 主动模式数据端口(服务器源端口) | TCP 20 |
| 被动模式数据端口 | 服务器动态指定(常配 40000–50000) |
| 隐式 FTPS 端口 | TCP 990 |
| SFTP 端口 | TCP 22(SSH) |
| TFTP 端口 | UDP 69 |
| 核心 RFC | RFC 959 |
| 被动模式应答码 | 227(PASV)/ 229(EPSV) |
| 端口计算公式 | p1 × 256 + p2 |
| 匿名用户名 | anonymous 或 ftp,密码填邮箱 |
关键应答码:150 准备传输 · 200 成功 · 220 就绪 · 226 传输完成 · 227 被动模式 · 230 登录成功 · 250 操作完成 · 257 路径已创建 · 331 需要密码 · 425 数据连接失败 · 530 未登录 · 550 文件不存在或无权限
常见面试题
FTP 为什么要用两个端口? 采用带外控制(out-of-band)设计:控制连接(21)全程保持只传命令与应答,数据连接按需建立只传字节流。好处是传输过程中控制通道仍畅通(可随时
ABOR中止),且数据流上无需任何协议头——连接关闭即代表传输结束。主动模式和被动模式的区别?为什么现在都用被动? 主动模式由服务器从 20 端口向客户端发起数据连接,被动模式由客户端向服务器的临时端口发起。由于 NAT 普及和客户端防火墙默认拒绝入站连接,服务器几乎不可能主动连上客户端,所以现代一律用被动模式。
被动模式下服务器返回私网 IP 怎么办? 服务器在 NAT 后时,
227应答里会带内网地址,客户端连不上。解决方式有二:① 配置pasv_address为公网 IP(vsftpd);② 使用EPSV(RFC 2428),其229应答只返回端口不返回 IP,客户端直接复用控制连接的目标 IP,天然规避此问题。FTP 为什么对防火墙不友好? 数据连接的端口号写在应用层载荷里(
PORT命令和227应答),防火墙必须做深度包检测(ALG/conntrack 模块)解析并动态放行。一旦启用 FTPS 加密,ALG 无法解析,就只能手工静态放行整段被动端口范围。FTPS 和 SFTP 有什么区别? 名字像但毫无关系。FTPS 是 FTP 加上 TLS,仍是双连接、仍用 21/990 端口、仍有被动模式问题;SFTP 是 SSH 协议的一个子系统,单条 TCP 22 连接、二进制协议、天然穿 NAT,与 RFC 959 没有任何继承关系。生产环境推荐 SFTP。
ASCII 模式和二进制模式选错会怎样? ASCII 模式会转换换行符(CRLF ↔ LF)。用它传 zip、exe、图片等二进制文件时,文件中恰好为
0x0D/0x0A的字节会被改写,导致文件损坏、大小不符、校验失败。规则:非纯文本一律先binary(TYPE I)。什么是 FTP Bounce 攻击? 攻击者用
PORT命令让 FTP 服务器向任意第三方主机的任意端口发起数据连接,从而借服务器之手进行端口扫描或绕过防火墙访问内网。现代 FTP 服务器默认拒绝PORT指向与控制连接源 IP 不一致的地址,nmap --script ftp-bounce可检测。匿名 FTP 的安全注意事项? 必须
chroot隔离;默认只读;若需开放上传,上传目录应设为只写不可读不可列(防止被当作违规内容中转站);限制并发与带宽;定期审计上传内容。ls卡住但登录正常,是什么问题? 一定是数据连接问题——LIST命令同样需要建立数据连接。排查方向:切换到被动模式、检查服务器被动端口范围是否放行、检查227返回的 IP 是否可达。为什么浏览器不再支持 FTP 了? 明文传输、无完整性保护、双连接模型与现代安全模型(安全上下文、混合内容策略)冲突、使用率极低而维护成本高。Chrome 95、Firefox 90 起已彻底移除,文件分发场景已由 HTTPS 完全接管。