You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python ftplib连接EC2 vsftpd报错ConnectionRefusedError[Errno111]求助

排查EC2上vsftpd的ConnectionRefusedError问题

首先,ConnectionRefusedError基本指向网络层面不通或者FTP服务未正常运行,结合你说的能连其他FTP服务器,咱们从EC2和vsftpd的配置入手一步步排查:

1. 先检查EC2安全组配置

这是最常见的坑!因为vsftpd用了被动模式,你需要同时开放两个端口段:

  • 控制端口:21/TCP(FTP默认控制端口)
  • 被动数据端口:1024-1048/TCP(你配置的pasv_min_portpasv_max_port范围)
    确保安全组的入站规则里添加了这两个端口,来源暂时可以设为你的本地IP(测试用,之后再缩小范围),不要直接用0.0.0.0/0(不安全)。

另外,别忘了检查EC2所在子网的网络ACL,默认是允许所有出入,但如果之前改过,要确保ACL也允许这两个端口的入站和出站流量。

2. 确认vsftpd服务是否正常运行

登录到你的EC2实例,执行以下命令查看服务状态:

systemctl status vsftpd

如果服务没启动,先启动它:

systemctl start vsftpd

如果启动失败,查看日志找原因:

journalctl -u vsftpd -f

常见的启动失败原因包括配置文件语法错误,比如pasv_address填错了IP,或者端口范围冲突。

3. 验证EC2本地能否连接FTP

在EC2上本地测试连接,排除网络问题:

ftp localhost

或者用私网IP:

ftp 你的EC2私网IP

如果本地能正常登录,说明vsftpd服务没问题,问题出在外部网络(安全组/ACL);如果本地也连不上,那就是vsftpd的配置有问题。

4. 检查vsftpd配置细节

打开/etc/vsftpd/vsftpd.conf,重点核对这些配置:

  • pasv_address:你填的是EC2的公网IP吗?如果是私网IP,外部客户端无法访问,必须填公网IP;另外pasv_addr_resolve=YES在这里如果填的是IP的话其实可以设为NO,避免不必要的解析。
  • listen=YESlisten_ipv6=NO:如果你的EC2没开IPv6,把listen_ipv6设为NO,避免vsftpd只监听IPv6端口。
  • ssl_enable:如果设为YES,说明vsftpd强制使用TLS加密连接,这时候你的Python代码用普通FTP类会被拒绝,需要改用FTP_TLS
    from ftplib import FTP_TLS
    with FTP_TLS('你的EC2公网IP') as ftp:
        ftp.login(user='my user', passwd='my password')
        ftp.prot_p()  # 切换到加密数据连接,避免被动模式下的明文传输问题
        ftp.cwd('/MY_DIR')
        ftp.dir()
    

5. 检查EC2上的防火墙

如果EC2用了firewalld或者iptables,要确保允许FTP相关端口:

针对firewalld:

# 允许FTP服务
firewall-cmd --add-service=ftp --permanent
# 允许被动数据端口范围
firewall-cmd --add-port=1024-1048/tcp --permanent
# 重载规则
firewall-cmd --reload

针对iptables:

# 允许控制端口21
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
# 允许被动数据端口
iptables -A INPUT -p tcp --dport 1024:1048 -j ACCEPT
# 保存规则
iptables-save > /etc/sysconfig/iptables

6. 对比NodeJS脚本的差异

如果你NodeJS脚本能成功连接,看看它的配置:

  • 是否用了TLS?
  • 是否手动指定了被动模式?
  • 端口是否正确?
    可以把Python代码的参数和NodeJS对齐,比如手动设置被动模式:
from ftplib import FTP
with FTP('你的EC2公网IP') as ftp:
    ftp.set_pasv(True)  # 显式开启被动模式,和vsftpd配置匹配
    ftp.login(user='my user', passwd='my password')
    ftp.cwd('/MY_DIR')
    ftp.dir()

内容的提问来源于stack exchange,提问作者RonanT

火山引擎 最新活动