☰
FTP连接失败排查:拒绝连接与没有到主机的路由分层定位
2026/10/26 19:20:42 网站建设 项目流程

FTP 这个东西说起来老,但真到要用的场合一点不含糊——老系统的对账文件、设备日志回传、第三方接口的批量数据交换,很多还压在它身上。而一旦连不上,报出来的那两句话往往只有两种形态:ftp connect: 拒绝连接和ftp connect: 没有到主机的路由。前者是 TCP 层被人当面关上了门,后者是网络层压根没找到门在哪。这两种报错看起来都像“连不上”,但排查路径几乎是两条不同的路,混着查只会把自己绕进去。

这篇内容面向的是正在被 FTP 连接问题卡住的人:不管是刚接手运维的新手,还是写了几年脚本、被客户一句“你们 FTP 连不上”怼回来的开发。下面我会把这两类报错的底层成因拆开讲清楚,再给出一套可以照着敲命令的分层排查流程,最后附上被动模式、防火墙、云上安全组这些实际最容易翻车的环节。文中涉及的系统和配置均按通用发行版描述,具体路径以你自己环境为准。

1. 先搞清楚两种报错到底差在哪

很多人排查 FTP 的第一步是打开客户端反复重连,看运气。这个动作除了消耗耐心没有别的产出。真正该做的第一件事,是把这两句报错翻译成网络分层里的具体位置。它们对应的不是同一个层,也不是同一类故障。

1.1 拒绝连接:TCP 层收到的那个 RST 包

拒绝连接(Connection refused)在协议层面的含义非常明确:客户端发出了 SYN,对端回了一个 RST。这说明什么?说明数据包已经成功到达了目标主机,路由是通的,目标主机的内核也正常处理了这个包,只是内核告诉客户端“这个端口上没有任何进程在等你的连接”,于是回了拒绝。

这条链路里,路由器、交换机、中间网络设备全都是好的,问题百分之百出在目标主机这一侧的应用层或者主机防火墙层。你可以把它理解成:地址找对了,楼也进去了,前台告诉你“这个房间没人”。

具体到 FTP,21 端口被拒绝,最常见的几个原因按出现频率排大概是:

  • FTP 服务进程根本没起来,或者起来之后崩了;
  • 服务起来了,但只监听了127.0.0.1,外部从公网或内网其它机器连进来就等不到;
  • 主机防火墙用了REJECT --reject-with tcp-reset这类策略,主动回 RST;
  • 端口写错了,客户端连 21,服务端改成了 2121,或者中间做了端口映射但映射规则没生效;
  • 端口被别的进程占了,FTP 启动失败,表面上像是没开。

注意最后一条特别有迷惑性。systemctl status显示 active,但实际绑定失败了,这种情况在配置改过端口、或者机器上跑了两套同类服务时很常见。

1.2 没有到主机的路由:网络层就已经断了

没有到主机的路由(No route to host)是另一回事。它通常意味着客户端的协议栈在发包阶段就没有找到可达路径,或者是中途收到了 ICMP 的不可达消息。跟“拒绝连接”比起来,它更靠下、更靠前。

典型场景有这么几类。第一类是客户端本机的路由表里没有到目标网段的条目,也没有默认网关,包发不出去。第二类是目标主机不在同一个二层网络,中间网关不认识这个网段。第三类是防火墙策略把包丢了,并且回了一个 ICMP host prohibited,客户端就会把它解释成“没有到主机的路由”。第四类是 ARP 解析失败,同网段内目标主机没响应 ARP 请求,内核报 host unreachable。

这里有个很关键的认知点:没有到主机的路由不一定真的是路由问题。如果防火墙用REJECT --reject-with icmp-host-prohibited,客户端收到的就是 ICMP 类型 3 代码 10,表现和真的路由不通几乎一模一样。我在实际排查里遇到过好几次,最后发现是目标机上的防火墙规则顺序写反了,把允许规则放在了拒绝规则后面。

而如果是DROP策略,客户端那边通常表现为连接一直挂着,最后超时,而不是立刻报错。所以“立刻报错”和“转圈到超时”,是区分 REJECT 和 DROP 的一个很实用的手感。

1.3 一张表分清两类故障的边界

对比项拒绝连接没有到主机的路由
报错层级传输层(TCP)网络层(IP/ICMP)
报文特征收到 RST收到 ICMP 不可达,或本机路由失败
目标主机是否可达可达,内核正常响应可能不可达,也可能被策略伪装成不可达
服务是否在监听没监听或监听地址不对与服务监听状态基本无关
常见原因服务未启动、绑 127.0.0.1、防火墙 REJECT路由缺失、网关错误、防火墙 ICMP REJECT、网段隔离
排查起点目标机ss -lntp客户端ip route与ping

把这张表记在心里,后面所有动作都是往下钻。拿反了方向,就会出现“明明防火墙全放开了还是连不上”这种僵局,因为问题根本不在防火墙的策略内容上,而在包有没有到。

2. 排查前的准备:把“分层”这件事落到命令行上

分层排查不是一句口号,它得变成一条固定顺序的命令清单。顺序对了,一次就能把范围砍掉一半;顺序乱了,改了一堆配置,问题还在原地。

2.1 排查顺序为什么必须是自下而上

假如 FTP 连不上,我先看服务状态还是先 ping?答案必须是先 ping。理由很直白:如果网络层都不通,你去看/etc/vsftpd/vsftpd.conf里的每一个参数都是白费。反过来,如果 ping 得通、端口探测被拒,那再去查服务配置才有意义。

我固定的排查顺序是四步,一步不跳:

  1. 链路与地址:确认本机网卡有没有地址、掩码对不对、网关通不通;
  2. 网络可达:ping目标 IP,看是超时、不可达还是通;
  3. 端口可达:telnet或nc探 21 端口,看是拒绝还是超时;
  4. 应用状态:服务进程、监听地址、配置文件、日志。

这四步跑完,故障基本已经被锁死在某一层了。下面每一步我会展开说,但顺序千万别换来换去。

2.2 手上要备好的几把工具

工欲善其事,工具先装齐。基础镜像里常常缺telnet和nc,很多人到现场才发现敲不出来。

  • ping:基础连通性,几乎所有系统自带;
  • ip route/route -n:看路由表和默认网关;
  • telnet或nc -vz:探测端口,判断拒绝还是超时;
  • traceroute或mtr:看路径在哪一跳断掉;
  • ss -lntp:看本机监听端口和对应进程;
  • tcpdump:抓包看 SYN 有没有发出去、有没有回包,这是终极大招;
  • firewall-cmd --list-all/iptables -L -n -v:看防火墙实际生效规则。

提示:在某些精简系统上telnet客户端和nc默认都没装。提前准备好,比到了现场临时找包要省太多时间。

2.3 记录基线信息,别一上来就改配置

我踩过最亏的一次坑,是接手一台别人配过的机器,一上来就怀疑防火墙,结果把本来正确的规则改坏了,最后发现只是 FTP 配置里listen=NO。从那以后我给自己定了个规矩:动手之前先把现场信息原样记录一份。

至少要记下这些:目标机的ip addr、ip route、ss -lntp | grep 21、防火墙规则全量输出、FTP 服务状态与最近 50 行日志。客户端这边记下ip route和ping结果。这些信息除了帮你定位,还有一个作用——出问题时能快速回滚,不至于越修越乱。

2.4 用 tcpdump 看清 SYN 的去向

这一步很多人觉得高级,其实它是最朴素的判断手段。在服务端执行抓包,同时在客户端发起连接:

# 服务端抓 21 端口的包 tcpdump -i any -nn port 21 -c 20

如果抓到了客户端来的 SYN,但服务端没回 SYN-ACK,那就是本机没监听或者防火墙拦了;如果回了 RST,那就是端口没人等,对应“拒绝连接”;如果压根没抓到 SYN,问题在中间网络或者路由,对应“没有到主机的路由”这一类。一次抓包,能省掉半小时的猜测。

3. 拒绝连接(Connection refused)的逐层拆解与修复

确定是“拒绝连接”之后,排查范围就缩小到目标机内部了。下面这四步我基本按顺序来,绝大多数情况在第二步就能定位。

3.1 第一步:确认服务到底起没起

先在目标机上执行:

systemctl status vsftpd

看两个东西:Active那一行是active (running)还是failed,以及下面日志里有没有Failed to start之类的内容。如果状态是 failed,直接看日志:

journalctl -u vsftpd -n 80 --no-pager

日志里常见的是配置文件语法错误、端口被占用、权限不足。比如500 OOPS: could not bind listening IPv4 socket基本就是端口被占了或者配置冲突。

如果状态是 running,也别高兴太早。继续看监听:

ss -lntp | grep -E ':(21|ftp)'

正常应该看到类似LISTEN 0 32 0.0.0.0:21 0.0.0.0:* users:(("vsftpd",pid=1234,fd=3))的输出。如果这里是127.0.0.1:21,那就是下一个问题了。

3.2 第二步:确认监听地址绑对没绑对

ss输出里那个0.0.0.0:21和127.0.0.1:21的区别,决定了外部能不能连进来。0.0.0.0表示监听所有 IPv4 地址,127.0.0.1表示只听本机回环。

造成只听回环的原因,在 vsftpd 上通常是这两行配置:

listen=YES listen_address=127.0.0.1

listen_address一旦被指定成回环地址,外部连接必然被拒。改法是把这一行注释掉,或者明确写成机器的业务 IP:

listen=YES listen_ipv6=NO # listen_address=127.0.0.1

改完记得systemctl restart vsftpd,然后再用ss确认一次。这里有个细节:listen=YES和listen_ipv6=YES不能同时打开,否则 vsftpd 启动会直接报错退出,而systemctl status有时候显示得很含糊,容易误判成服务正常。

3.3 第三步:防火墙是 REJECT 还是 DROP

监听没问题,端口也对外了,那就要看防火墙。先确认防火墙状态:

# firewalld 环境 firewall-cmd --state firewall-cmd --list-all # iptables 环境 iptables -L INPUT -n -v --line-numbers

判断的关键在于规则里用的是REJECT还是DROP。REJECT会往客户端回一个消息,DROP是直接丢弃、不回任何东西。所以:

  • 客户端立刻报“拒绝连接”,多半是REJECT --reject-with tcp-reset;
  • 客户端一直转圈到超时,多半是DROP;
  • 客户端报“没有到主机的路由”,可能是REJECT --reject-with icmp-host-prohibited。

放行 21 端口的写法,firewalld 环境下:

firewall-cmd --permanent --add-service=ftp firewall-cmd --reload

或者按端口放行:

firewall-cmd --permanent --add-port=21/tcp firewall-cmd --reload

iptables 环境下:

iptables -I INPUT -p tcp --dport 21 -j ACCEPT

注意-I是插到链首,-A是追加到链尾。如果原有规则里有前置的拒绝规则,-A加在后面的允许规则根本不会被匹配到。这就是我在第 1 节提到的“规则顺序写反”的典型后果。

注意:改 iptables 规则前先确认有没有持久化机制,否则重启后规则全丢,第二天又是同一个故障。iptables-save配合netfilter-persistent或iptables-services是常见做法。

3.4 第四步:云主机上的安全组与端口映射

如果目标机跑在云上,主机内部防火墙全放开了还是拒绝连接,那就要往上找一层。云平台通常有独立于操作系统的网络访问控制,一般叫安全组或者网络 ACL,它在实例外面生效,你在机器里iptables -L是看不到的。

排查方式是登录云控制台,找到该实例绑定的安全组,看入方向规则里有没有放行 21 端口,源地址范围是否覆盖了你的客户端 IP。这里最常见的两个坑:一是安全组只放行了内网地址,而你从公网连;二是规则的优先级被更靠前的拒绝规则盖掉了。

还有一种情况是中间做了端口映射,比如公网 2121 映射到内网 21。这时候客户端必须连 2121,连 21 自然是被拒。同时被动模式还要额外处理数据端口,这个在第 5 节展开。

3.5 验证与回归测试

改完不要只在自己机器上试一次就收工。我的验证清单是这样的:

  1. 本机telnet 127.0.0.1 21,确认服务活着;
  2. 同网段另一台机器telnet 内网IP 21,确认内网可达;
  3. 客户端所在网络telnet 公网IP 21,确认外部可达;
  4. 用真实 FTP 客户端登录一次,做一次ls和一次put;
  5. 重启一次服务,再重复第 4 步,确认配置持久化没问题。

第 5 步很多人省掉,结果下次机器重启故障复现。配置这东西,不重启验证一遍就等于没改。

4. 没有到主机的路由(No route to host)的逐层拆解与修复

这类报错的排查思路和上一节完全不同。核心是回答一个问题:包到底有没有离开客户端,以及离开之后走到了哪一跳。

4.1 先 ping 一下,但 ping 不通不代表服务有问题

第一步永远是ping 目标IP。但要注意,ping不通有三种可能,含义完全不同:

  • Destination Host Unreachable:本机或中间设备明确告诉你到不了,路由或 ARP 有问题;
  • Request timeout:包发出去了,没有任何回应,可能是对方禁 ping,也可能是防火墙 DROP;
  • Name or service not known:这是域名解析问题,压根还没到网络层。

关键认知是:服务器禁 ping 是很常见的加固手段,ping 不通不代表 FTP 连不上。所以 ping 只能作为参考,不能作为结论。真正有决定性的还是端口探测:

nc -vz -w 3 目标IP 21

或者:

telnet 目标IP 21

看返回是Connection refused、Connection timed out还是No route to host。这三者的含义和排查方向完全不同,前面表格里已经对上了。

4.2 路由表与网关检查

确认是本机路由问题时,先看路由表:

ip route

输出里要关注两件事:有没有到目标网段的具体路由,以及default via后面那个网关地址是不是当前网段的合法地址。如果默认网关写错了,比如网段是192.168.10.0/24,网关却写成了192.168.20.1,那所有跨网段的包都发不出去。

再看本机地址和掩码:

ip addr

掩码写错是很容易被忽略的坑。把/24写成/16,本机会认为整个192.168.0.0/16都在同一个二层网络里,于是对本来需要经过网关的地址直接发 ARP 请求,结果自然是 host unreachable。这种错误在手工配 IP 的机器上出现频率相当高。

4.3 防火墙 DROP 策略的典型表现

前面说过,DROP通常表现为超时而不是“没有到主机的路由”,但如果规则用的是REJECT --reject-with icmp-host-prohibited,客户端收到的就是 ICMP 类型 3 代码 10,报错文案和真正的路由不通一模一样。

判断方法是看目标机上的规则:

iptables -L INPUT -n -v --line-numbers

如果看到类似这样的规则:

REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

并且它排在允许 21 端口的规则前面,那故障原因就找到了。处理方式是调整顺序,把允许规则插到它前面:

iptables -I INPUT 1 -p tcp --dport 21 -j ACCEPT

-I INPUT 1里的1表示插到第一条。这个数字很关键,插错位置等于没插。

4.4 网段隔离、VLAN 与云上子网

如果客户端和服务端不在同一个二层网络,中间又有多层网络设备,那就要考虑策略隔离了。企业内网常见的做法是把办公网、服务器网、测试网分到不同 VLAN,VLAN 之间的访问由三层设备上的 ACL 控制。ACL 默认拒绝的时候,表现出来就是“没有到主机的路由”。

云上的情况类似,但对象换成了子网和路由表。两个子网之间如果没有对等连接或者路由条目,包就出不去。这时候在实例内部怎么改防火墙都没用,得去网络配置层面加路由。

排查手段是traceroute:

traceroute -n -T -p 21 目标IP

-T表示用 TCP 探测,-p 21指定端口。看输出在哪一跳开始出现* * *,就能大致判断阻断点在哪一层设备上。如果第一跳就是星号,问题在本机或网关;如果中间几跳正常、最后断了,问题在靠近目标的一侧。

4.5 复现验证方法

改完路由或者 ACL 之后,验证要覆盖两个方向。正向验证是从客户端 ping 和探端口,反向验证是从服务端 ping 客户端,同时看服务端有没有收到 SYN:

# 服务端抓包,确认有 SYN 进来 tcpdump -i any -nn 'tcp port 21 and tcp[tcpflags] & tcp-syn != 0'

抓到 SYN 说明网络通了,剩下的就是应用层的事;抓不到说明包还在路上被拦着。这个判定比反复改配置靠谱得多。

5. 连上了却传不了文件:被动模式那些坑

端口通了、登录成功了、ls也出来了,结果put一个文件卡死不动——这是 FTP 最经典的“第二步故障”。它跟前面两类报错不是一回事,但对使用者的感受是一样的:连不上。

5.1 主动模式与被动模式的本质区别

FTP 用两条连接:一条控制连接走 21 端口,一条数据连接传文件。控制连接永远是客户端主动连服务端,这个没问题。数据连接的方向取决于模式。

主动模式(PORT)下,服务端从自己的 20 端口主动连客户端的一个随机端口。问题在于客户端通常在 NAT 或者防火墙后面,服务端根本连不进去,于是卡住。

被动模式(PASV)下,客户端向服务端要一个端口,服务端返回一个随机高位端口,客户端主动去连这个端口。这个方向对客户端友好,所以现代客户端默认都用被动模式。

但被动模式又带来一个新问题:服务端返回的那个端口是随机的,防火墙如果只放行了 21,数据连接必然被拦。表现出来就是登录正常、列目录正常,一传文件就超时。

5.2 pasv_min_port 与 pasv_max_port 的配置

解决办法是把被动模式的端口范围固定下来,然后在防火墙上放行这一段。vsftpd 的配置是这样:

pasv_enable=YES pasv_min_port=30000 pasv_max_port=30100

范围选多大?按并发连接数估。每个数据传输占一个端口,理论最大并发数等于端口数量。一般内部使用 100 个端口足够,50 个并发以内完全扛得住。如果用户量大,可以放到 500 个。

如果服务端在 NAT 后面,还要加一行pasv_address,告诉客户端应该连哪个公网地址:

pasv_address=公网IP

这一行不加,服务端会把内网地址返回给客户端,客户端拿着一个内网 IP 去连,自然连不上。这是我见过最多的被动模式故障原因,没有之一。

5.3 防火墙放行数据端口

配置改完,防火墙同步放行:

firewall-cmd --permanent --add-port=30000-30100/tcp firewall-cmd --reload

云平台的安全组也要同步加一条规则,端口范围写30000-30100,协议 TCP。这一步经常被漏掉,因为在机器内部折腾半天都正常,一出公网就废。

还有 SELinux 这一层。如果系统开了 SELinux 且策略比较严,FTP 读写家目录会被拦:

getenforce setsebool -P ftpd_full_access on

-P表示持久化,不加的话重启就失效。改完用getsebool ftpd_full_access确认一下状态是 on。

6. 常见问题速查表与避坑经验

前面几节讲的是原理和流程,这一节讲的是我这些年实际踩出来的经验。有些坑在文档里不会写,但遇到了能让人折腾一整天。

6.1 排查速查表

现象最可能的原因快速验证处理动作
立刻报拒绝连接服务未启动 / 绑回环ss -lntp | grep 21启动服务,改listen_address
立刻报拒绝连接,服务正常防火墙 REJECTiptables -L -n -v放行 21,注意规则顺序
转圈后超时防火墙 DROPtcpdump看有无回包检查 DROP 规则与安全组
报没有到主机的路由路由缺失或 ICMP REJECTip route、traceroute补路由或调整 REJECT 类型
ping 通但端口不通服务未监听或端口错误nc -vz探端口核对端口与监听地址
登录成功但ls卡住被动模式端口被拦客户端开 PASV 调试日志固定 pasv 端口段并放行
登录成功但put失败目录权限或 SELinuxls -ld、getenforce改权限或开ftpd_full_access
重启后故障复现配置未持久化重启再测一遍iptables-save、--permanent

6.2 几个我踩过的坑

坑一:systemctl status是 active,但端口没起来。有一次配置文件里listen和listen_ipv6同时为 YES,vsftpd 启动后立刻退出,但 systemd 的重启策略让它反复拉起,status看到的永远是 active。真正定位是靠journalctl里的重复报错。所以看状态一定要配合看日志和看监听。

坑二:改完 iptables 忘了持久化。这个坑的杀伤力在于它有延迟——当天一切正常,第二天机器重启,故障原样复现,而且看起来像是“莫名其妙又坏了”。现在我的习惯是改完立刻iptables-save > /etc/sysconfig/iptables,firewalld 环境则确保每条命令都带--permanent。

坑三:客户端防火墙也拦。一直在服务端折腾,最后发现是客户端本机的出站规则拦了高位端口。被动模式下客户端要连服务端的 30000 以上端口,有些终端安全软件默认只放行常用端口。这个排查起来很快,在客户端抓个包就一目了然。

坑四:NAT 环境下的pasv_address忘了配。表现是内网用户全正常,外网用户一律传不了文件。因为服务端返回的是内网地址,外网客户端拿着192.168.x.x去连,当然连不上。这个问题的隐蔽性在于日志里看不出任何异常,只能靠抓包或者看客户端返回的 PASV 响应内容。

坑五:账号密码对了但登录被拒。这不是网络问题,是认证层。常见原因是ftpusers和user_list文件里默认拒绝了一批系统账户,或者chroot_local_user=YES配合家目录可写导致 vsftpd 拒绝登录。日志在/var/log/secure里,搜vsftpd关键字能直接看到原因。

6.3 长期运维上的一点建议

FTP 这套东西本身没有健康检查机制,出问题往往是被动发现的。我的做法是在监控里加两个探测点:一个是 21 端口的 TCP 连通性探测,另一个是真实的登录加列目录操作,频率五分钟一次。前者能发现服务挂了,后者能发现被动模式配置被改坏了。

另外,配置变更一定要留记录。FTP 的配置文件不长,但每一项都影响面很大,尤其是被动模式那几行。我见过一次事故,是有人为了“优化性能”把pasv_min_port和pasv_max_port注释掉了,结果防火墙规则对应的端口段全部失效,外网用户全部传不了文件,而内网测试一切正常,直到客户投诉才发现。

最后再分享一个小技巧:排查 FTP 问题时,尽量用命令行客户端ftp或lftp而不是图形客户端。命令行会原样输出服务端的响应码,比如227 Entering Passive Mode (192,168,1,10,117,40),这里面的数字就是服务端返回的被动端口,117*256+40=30000,一眼就能看出它返回的是不是内网地址、端口在不在放行范围内。图形客户端把这些信息全藏起来了,排查时等于蒙着眼睛。

我在实际处理这类问题的体会是,FTP 报错文案的区分度其实很高,拒绝连接和没有到主机的路由已经把排查方向指得很明确,难的不是判断,而是忍住不跳过验证步骤直接改配置。按链路、网络、端口、应用这四层老老实实走一遍,绝大多数问题在十分钟内就能定位到具体那一行配置上。

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

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

立即咨询