☰
外网无法访问内网FTP?分清主动与被动模式,搞定端口映射
2026/10/9 1:11:31 网站建设 项目流程

简介:针对外网无法访问局域网的FTP服务器这一典型网络故障,这份PDF提供了一套完整的实验分析与解决方法。文档面向网络管理员、运维人员及需要搭建FTP服务的学习者,重点讲解FTP协议中PORT主动模式与PASV被动模式的工作机制,并结合ADSL—NAT—PC的真实实验环境,演示了映射21端口、20端口及指定被动端口范围后的不同表现,通过对比抓包结果指出了NAT映射不完整导致数据链路中断的根因。资源为1个PDF文件,大小122KB,内容精炼,包含Serv-U配置、动态域名设置及防火墙兼容性调整等实用细节,已有1092人学习下载。阅读后可以清楚理解为何外网能连接却无法列目录或下载文件,并能参照文档中的映射思路,快速定位自家网络环境下的FTP访问故障,适合用于企业内网文件共享场景的排错参考。

1. 外网无法访问局域网 FTP 服务器:先分清控制链路和数据链路

FTP 服务器搭建好之后,最常遇到的现象是:外网能 ping 通、能登录、输完账号不报错,但一列目录就卡住,最后弹"打开 FTP 服务器上的文件夹时发生错误"。这个问题从 WinXP SP2 时代延续到今天,根本原因往往不是 Serv-U 装错了,而是 FTP 的数据链路方向和当前网络环境不匹配。FTP 和 HTTP 最大的区别是它有两条链路:一条命令链路(默认 21 端口),一条数据链路。数据链路建不起来,就会出现"能连不能传"的怪象。这份解决外网无法访问局域网 FTP 服务器问题的资料,核心是把两种模式、三组映射实验和排查步骤整理成可复现的参数,适合做企业文件共享对外发布、内网服务器映射到公网、以及有脚本定时抓取公司 FTP 数据的运维。照着实验参数走一遍,比自己到处猜要快得多。

2. FTP 两种工作模式:为什么“能登录”不等于“能传数据”

2.1 PORT 主动模式:服务器拿 20 端口反过来连客户端

Port 方式(主动模式)的完整流程可以拆成三步。第一步,客户端向服务器的 21 端口发起 TCP 连接,这条链路叫命令链路,也叫控制链路,登录、输命令都走它。第二步,当需要传输目录列表或文件时,客户端在命令链路上发送 PORT 命令,命令参数携带客户端本机的一个空闲端口。PORT 命令的格式是把 IP 的四个十进制数和端口号的高低位分别以逗号分隔,例如客户端 IP 是 192.168.1.50、数据端口是 3328,报文体就是 PORT 192,168,1,50,13,0,其中 13 和 0 拼出端口 13×256+0=3328。第三步,服务器收到 PORT 命令后,用自己的 20 端口向客户端的 3328 端口发起一条新的 TCP 连接,这条就是数据链路,目录列表和文件内容都从这条链路传输。

这里有两个容易忽略的细节。第一,数据链路是服务器主动发起的,方向是从服务器到客户端,只要客户端处于防火墙或者 NAT 后面,这条主动连接就很可能被拦掉。Windows 自带防火墙默认拦截入站连接,很多人在本地测试正常、换到外网环境就失败,本质上就是客户端设备上的防火墙把服务器主动发来的数据连接丢弃了。第二,命令链路在整个 FTP 会话期间一直保持,数据链路却是临时的,传完一个文件就断开,下一个文件再重新建立。理解了这两点,"能登录但不能列目录"这个现象就很好解释:登录走的是命令链路,列目录走的是数据链路,命令链路通,不代表数据链路能建起来。

和协议交互相关的还有一组响应码值得认识。列目录请求发送后,服务器会返回 150,表示数据连接即将建立、文件状态正常;传输完成后返回 226,表示关闭数据连接、请求操作成功。如果中途数据链路断开,客户端会收到 426 之类的响应,告诉你连接关闭、传输被中断。我一般会拿这些响应码配合抓包来定位问题,比单纯看界面报错信息准确得多。我在 Windows 命令行下用系统自带的 ftp 客户端复现时,看到的就是这个过程:连接后发 PORT 命令,然后长时间停留在等待目录列表的状态,直到超时。命令行 ftp 默认使用主动模式,这正是它在受限网络环境下经常卡在 ls 命令的原因之一。

2.2 PASV 被动模式:客户端反过来连服务器的高位端口

Pasv 方式(被动模式)把数据链路的发起方向调转过来。客户端依然先连服务器的 21 端口建立命令链路,但需要传数据时,发送的是 PASV 命令而不是 PORT 命令。服务器收到 PASV 命令后,临时打开一个高位端口,并返回 227 响应,格式类似 227 Entering Passive Mode (219,154,214,150,39,25)。括号里前四段是 IP 地址,后两段拼出端口号,39×256+25=10009。客户端拿到这个地址后,主动向服务器的 10009 端口发起数据连接。

被动模式对"客户端在防火墙/NAT 后面"的场景非常友好,因为数据连接由客户端发起,方向是出站,绝大多数防火墙和 NAT 都不会拦截出站连接。代价是问题被转移到了服务器侧:如果 FTP 服务器部署在局域网内部,它返回给客户端的 IP 必须是 NAT 出口的公网地址,同时临时监听的高位端口段必须在 NAT 上做整段映射。主动模式怕客户端躲在内网,被动模式怕服务器躲在内网,两侧只要有一侧处理不好,就会复现同样的"能连不能传"。做局域网文件共享时,如果只是内网使用,SMB 共享比 FTP 更省事;但一旦涉及公网访问,FTP 的两种模式哪个在起作用,直接决定端口映射方案怎么做。

还需注意,被动模式下数据传输通道和控制通道的生命周期与主动模式相同:控制信道一直保持连接,数据通道临时建立、用完即断。每个数据连接占用一个临时端口,传输完成后端口进入 TIME_WAIT 状态,短时间内不会立刻复用。这也是后面并发连接把端口挤爆的根源——不是服务器不支持并发,而是端口释放速度跟不上连接建立速度。

2.3 用一张表对比两种模式,并确认当前客户端在用哪种

对比项PORT 主动模式PASV 被动模式
命令链路客户端 → 服务器 21客户端 → 服务器 21
数据链路发起方服务器 20 → 客户端随机端口客户端 → 服务器高位端口
数据端口特点服务器固定 20服务器动态高位端口
适合谁在 NAT 后面适合服务器在 NAT 后面适合客户端在 NAT 后面
服务器侧要配置保证 20 端口可达固定被动端口段并整段映射

排障时确认当前模式有两条路。第一是看客户端日志,FileZilla 的报文日志会逐行显示 PORT 或 PASV 命令以及对应的响应码;第二是抓包,过滤条件写 tcp.port == 21,看命令链路上发的是 PORT 还是 PASV。命令行下用 ftp 加 -v 参数也可以看到原始报文,慢但零依赖。另外一个容易忽略的事实是,几乎没有哪个客户端的默认设置是全局统一的:IE 默认主动模式,FileZilla 默认"被动(推荐)",而 Serv-U 服务端可以限制只允许某一种模式。当客户端和服务端都被 NAT 挡在各自网络中时,惯例是让客户端用被动模式,服务器固定被动端口段并把外部地址配好,这样整条数据链路只需要打通服务器侧这一端。搞清楚模式归属再去查映射和防火墙,才不浪费排查时间。

除了模式切换,还有一个容易混淆的概念是数据连接是否加密。资料里的实验基于明文 FTP,如果你的环境使用 FTPS 或 SFTP,数据链路的建立方式会发生改变:FTPS 的被动模式通常要求显式 TLS 通道,端口行为类似 PASV 但握手包不同;SFTP 则是完全建立在 SSH 之上的另一套协议,不再有 PORT/PASV 之分。排查时先确认协议族,不要把 FTP 的结论直接套到 SFTP 上。

3. NAT 下三组端口映射实验:21、20、被动端口段分别解决什么

做外网访问内网 FTP 的实验,最忌讳的是凭感觉乱映射。资料里的三组实验按照"协议链路逐步放开"的方式推进:先只放开命令链路,再放开主动模式数据链路,最后放开被动模式数据链路。每一组都能得到清晰的结论,比一次性把所有端口全映射上去、出了问题不知道往哪查要可控得多。

3.1 实验环境与第一组:只映射 21 端口,两种模式都卡在列目录

复现环境沿用原始资料里的拓扑:出口是 ADSL 的公网地址 219.154.214.150,内网 NAT 网关地址 10.41.221.2,FTP 服务器 PC 地址是 10.41.221.6,服务器程序用 Serv-U。为什么用 Serv-U?因为它能显式设置被动模式的数据端口范围,第三组实验需要靠这个功能固定端口段;如果你用的是其他 FTP 服务器搭建方案,比如 vsftpd 或 Windows IIS FTP,思路完全一样,只是配置入口和参数名不同。

第一组实验只在 NAT 上映射了 21 端口到内网 PC,没做任何额外映射。结果非常典型:PORT 方式能连接、不能列目录;PASV 方式能连接、不能列目录。这个结果说明 21 端口映射只解决了命令链路的问题,数据链路完全没有出口。PORT 模式下,服务器想从内网主动连外网客户端,这种出方向的连接到了 NAT 网关没有对应规则,直接被丢弃;PASV 模式下,服务器临时打开的端口没有映射,公网客户端发起的数据连接也进不来。

# 在 FTP 服务器上快速确认命令链路和数据链路状态 netstat -ano | findstr :21 netstat -ano | findstr :20 netstat -ano | findstr "ESTABLISHED"

第一条命令找命令链路是否已建立,第二条找主动模式的数据端口,第三条看全部已建立连接。触发列目录动作后,如果在 20 或高位端口上始终没有出现新的 ESTABLISHED 连接,数据链路基本没有建立起来。实际中有个常见场景:气象服务器定时从公司内网 FTP 拉数据,脚本每 5 分钟跑一次任务,如果端口映射不完整,报错日志里全是超时记录,这时候排查的优先级是端口映射,而不是先改脚本的重试逻辑。

3.2 第二组:补上 20 端口映射,PORT 全通但 PASV 仍然失败

第二组实验把 20 端口也映射到内网 PC,Serv-U 保持默认的 PORT 模式。结果变成:PORT 方式能连接、能列目录、能下载文件;PASV 方式能连接、不能列目录、不能下载文件。

PORT 和 PASV 在同一组映射下表现完全不同,核心原因就是数据链路的发起方向。PORT 模式下,数据连接由服务器从 20 端口主动发起,只要服务器侧的 20 端口映射到位,公网客户端就能正常收到目录列表和文件数据;PASV 模式下,数据连接由客户端向服务器的高位端口发起,而高位端口没有任何映射,连接到了 NAT 网关就断了。所以映射 20 端口救得了主动模式,却救不了被动模式。这个不对称结论在排查时非常好用:你只需要在客户端换一种模式测试,看结果跟着哪一侧变,就能快速判定问题在服务器侧还是客户端侧。

这里有一个操作细节值得注意:映射 20 端口之前,先确认服务器本机的 20 端口确实由 Serv-U 监听。如果服务器还运行着其他网络服务,20 端口可能被占用,Serv-U 会动态改端口,越映射越对不上。检查方法是启动 Serv-U 后立刻执行 netstat -ano | findstr :20,确认 20 端口处于 LISTENING 且进程对应;只要端口被占,先到 Serv-U 设置里把主动模式数据端口强制改回 20 并解决占用冲突,再谈映射。另外,服务器 PC 自带的 Windows 防火墙也要放行 20 端口的入站连接,否则公网侧来的数据连接到了 PC 网卡就被本地防火墙丢掉,映射做得再对也没用。

3.3 第三组:固定被动端口段并整段映射,PASV 才真正走通

第三组实验把 20 端口映射关掉,改在 NAT 上映射 10001-10004 到内网 PC,并在 Serv-U 里把被动模式端口范围限制为 10001-10004。结果是:PORT 方式不能列目录、不能下载文件;PASV 方式能连接、能列目录、能下载文件。

Serv-U 设置被动端口范围的位置在对应域的 Settings → Advanced 页签,勾选 Allow passive mode data transfer,把端口范围填成 10001-10004。保存后 Serv-U 会把这几个端口全部置为监听状态,客户端发送 PASV 命令时,服务器从范围里挑一个可用端口返回,而不是用系统随机高位端口。这个"固定端口段"的能力是 NAT 到网环境的关键:端口不可控就没法在 NAT 和防火墙上做精确放行,所以只要是给内网 FTP 做对外发布,第一步就应把被动端口段固定下来,而不是等出了问题再来堵。

资料里提到端口范围限制在 1024-5000 之间,超过 5000 后 Serv-U 建立被动连接会失败。实测确实如此,具体原因资料没有深究,我的经验是部分版本对超高位被动端口存在兼容问题,稳妥做法是把端口段保持在 1024-5000 区间内选一段,比如 30000-30050,同样能达到目的。Linux 网关上的映射命令参考如下:

# 命令链路:把公网 21 端口转发到内网 FTP 服务器 iptables -t nat -A PREROUTING -d 公网IP -p tcp --dport 21 -j DNAT --to-destination 10.41.221.6:21 # 被动数据链路:整段转发被动端口段 iptables -t nat -A PREROUTING -d 公网IP -p tcp --dport 30000:30050 -j DNAT --to-destination 10.41.221.6

参数说明:PREROUTING 链在路由决策之前处理入站流量,DNAT 把目标地址改写成内网服务器地址;第一条只针对 21 端口,第二条针对整个端口段。如果用的是华为 ensp 搭模拟环境验证同类连通性,思路一致,只是把 iptables 换成接口策略加 NAT Outbound 的端口段配置。很多文章只教你映射 21 就收工,实际完整的对外发布方案必须包含被动端口段这一项,否则外网客户端依旧会卡在列目录。

还有一个从抓包里得到的差异值得记下来。资料指出微软官方文档对 PASV 协商过程的描述与实际抓包结果不符:文档认为服务器端口被占用时会返回 UNACK、再进行协商,但抓到的报文显示,Serv-U 在设置被动范围后端口立刻进入监听状态,客户端发 PASV 时服务器直接返回一个可用端口,不存在反复协商。如果在其他 FTP 服务器程序上遇到协商失败的报文,先看服务器支不支持固定被动端口段,支持的话优先用固定段,比依赖动态协商更可控。

三组实验结果可以收拢成一张对照表:

映射内容PORT 结果PASV 结果结论
仅 21能连不能列能连不能列数据链路完全没通
21 + 20全通能连不能列主动模式可用,被动仍断
21 + 被动段能连不能列全通固定被动端口段生效

4. 外网访问内网 FTP 的排查清单:五条最容易踩的坑

下面五条是我在复现和实际运维中被反复教育过的坑,每一条都按"现象 → 原因 → 解决"的顺序记录。排查时建议从第一条开始按顺序走,因为后四条本质上都是第一条的细化分支。

4.1 能登录但不能列目录:先分清哪条链路断了

现象:外网客户端输入账号密码后正常进入 FTP,执行 LIST 命令后一直转圈,最终报"打开 FTP 服务器上的文件夹时发生错误,请检查是否有权限访问该文件夹"。

原因:命令链路通、数据链路不通。绝大多数情况是只映射了 21 端口,数据端口段没有映射;也可能是客户端使用的模式与服务器端可提供的数据链路方向不匹配。原文在 Win98、WinME、Win2000、Win2003 下都能正常上传,到 WinXP SP2 就出问题,就是因为系统防火墙默认策略变了,入站数据连接被拦。

解决:在 FTP 服务器上执行 netstat,观察列目录瞬间是否出现新的 ESTABLISHED 连接;同时把客户端切换为另一种模式再试一次。PORT 能传而 PASV 不能传,基本锁定为服务器被动端口段未映射;反过来 PASV 能传而 PORT 不能传,大概率是客户端侧防火墙拦截了入站数据连接。这一条是定位问题的总纲,后面四条都是它的具体分支。

4.2 被动模式把内网 IP 回给了客户端

现象:客户端设置为被动模式,登录正常,发 LIST 后超时,客户端日志里出现 227 Entering Passive Mode (10,41,221,6,39,25),括号里是内网地址。

原因:PASV 响应中携带的地址是服务器本机网卡地址。服务器在 NAT 内部时,返回的是 10.41.221.6,公网客户端无法路由到这个内网地址,数据链路自然建不起来。这是一个非常隐蔽的雷,因为端口映射做得再完整,只要 227 响应里的地址不对,客户端永远连的是错误目标。

解决:在 Serv-U 的 Domain → Settings → Advanced 里勾选 Allow passive mode data transfer,IP 地址框按出口类型填写。动态拨号出口留空,让服务器先向外网查询当前出口地址再返回;固定出口直接填固定公网 IP。资料里的做法是申请 tz0.com 的动态域名 key,填入 Serv-U 的 Dynamic DNS 页签,效果就是让 PASV 响应返回外网地址。换其他 FTP 服务器时,这类功能通常叫"被动模式外部 IP 地址"或者 PASV Address,找对应参数填公网 IP 即可。

提示:227 响应是排查内网 IP 问题的第一现场,客户端日志里看到括号内是 10.x、192.168.x、172.16.x 这类地址时,直接去检查服务器被动模式的外部地址配置,不要纠结端口映射。

4.3 被动端口段开得太小:多用户一挤就断

现象:单个用户测试一切正常,多人同时上传或下载时,部分用户列目录失败、传输中断,或者提示"无法获取目录列表"。

原因:每个数据连接临时占用一个被动端口,连接关闭后端口进入 TIME_WAIT 状态,短时间内不会被重新分配。被动范围只开 4 个端口时,并发稍微一高就没有可用端口了。

解决:把被动端口段放宽到 100 个以上,例如 30000-30100,NAT 和防火墙同步放行整段。对大多数文件共享场景,端口数量比单连接速度上限更重要,宽端口段带来的稳定性提升远高于在单个连接上做限速。如果环境有安全策略限制大范围端口,可以按"同时在线数 × 预留缓冲"来折算范围,而不是拍脑袋开 4 个。

4.4 IE 的文件夹视图和被动 FTP 选项互相打架

现象:服务器端被动模式配置正确,客户端用 IE 打开 FTP 地址仍然卡在列目录,而且 IE 高级设置里明明勾选了"使用被动 FTP"。

原因:IE 高级选项卡下有两个相关选项,一个是"为 FTP 站点启用文件夹视图",一个是"使用被动 FTP(为防火墙和 DSL 调制解调器兼容性)"。当文件夹视图处于启用状态时,IE 表现得像标准模式客户端,即使被动 FTP 勾选了也不生效。这个坑从 WinXP SP2 时代就存在,资料里专门点名了它,因为两个选项的名字看起来互不相关,很少有人会同时检查。

解决:在 IE 的工具 → Internet 选项 → 高级里,取消勾选"为 FTP 站点启用文件夹视图",保留"使用被动 FTP"。更省事的做法是引导用户用 FileZilla 这类专业客户端,模式可显式固定、日志清晰,比在浏览器里来回勾选高效得多。排查时如果看到用户用的就是 IE,优先把这两个复选框的当前状态都列出来再判断。

4.5 防火墙只放行 21:被动数据端口被安全策略拦掉

现象:端口映射正确、Serv-U 被动范围也设置了,外网连接在登录成功后仍然被重置,抓包看到 SYN 发出后没有响应。

原因:防火墙或安全组规则只放行了 21 端口,被动端口段被策略丢弃。被动模式要求服务器可以打开任意短暂端口,管理员需要放行整个端口段,很多安全基线默认拒绝这种大范围端口。

解决:把防火墙规则收紧成只放行 TCP 21 和 TCP 被动端口段,端口段内全放行,段外全拒绝。同时关闭匿名登录、限制根目录写权限、配置访问 IP 白名单,把 FTP 服务器的对外暴露面控制在最小范围。如果你还要同时开放远程桌面之类的跨局域网服务,不要把端口混进同一个规则段,逐条规则映射到不同内网主机,出问题时才不会被一条大范围规则干扰判断。

5. 抓包验证数据链路与固定排查习惯

这套排查流程我前后踩了差不多一个星期才完整跑通,最后收尾的验证步骤非常简单,也最容易被跳过。先用专业客户端把传输模式固定为被动,比如 FileZilla 站点设置里的传输模式选择"被动"并保存,完成连接后立刻在服务器侧看 netstat,确认出现来自公网 IP 的 ESTABLISHED 连接,并且本地端口落在被动端口段内:

# 在 FTP 服务器上确认被动端口处于监听状态 netstat -ano | findstr LISTENING # 查看与外部客户端之间的数据连接状态 netstat -ano | findstr ESTABLISHED

确认监听到位后,再从公网侧用 telnet 对被动端口段里的端口补一次连接测试,能建立说明 NAT 和防火墙整条链路的放行都生效了。这一步对只改过一次配置的场景特别有效,能快速区分"配置没生效"和"配置生效但链路不通"。如果还有疑问,最后抓一次包,看 227 响应里返回的地址是不是公网 IP,这一步能直接把第 4.2 节那个内网 IP 的雷排除掉。

抓包的时候,如果环境允许,我习惯在公网侧放一台持续抓包的机器,过滤条件写 tcp.port == 21 or (tcp.port >= 30000 and tcp.port <= 30100),这样整条交互过程一目了然:先是 21 端口上的握手包和 FTP 应答,随后出现客户端向 30000 段发起的 SYN,最终看到数据通道建立。相比只看服务端日志,这种验证方式能一次确认命令链路、数据链路、NAT 转发三条路径是否同时正常。

从那以后,我每次给内网 FTP 做对外发布都强制走一遍固定流程:先在 Serv-U 里固定被动端口段,再检查 NAT 映射是否覆盖整段端口,然后确认 PASV 响应返回的是外网地址,最后用公网客户端跑一次列目录和上传下载。四步走完再交付,基本不会再被"能登录不能传"这种问题找回来。这份 PDF 里的三组实验记录和报文分析可以拿来做对照复现,你的网络环境下跑出来的结果如果能和资料对上,说明整个排查路径你已经吃透了。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询