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_port到pasv_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=YES和listen_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




