PHP调用FTPS出现ftp_nlist()错误,需添加何种防火墙规则?
问题描述
在使用PHP进行FTPS文件传输时遇到报错:
ftp_nlist(): php_connect_nonb() failed: Operation now in progress (115)
演示代码如下:
<?php error_reporting(E_ERROR | E_WARNING | E_PARSE); ini_set('display_errors', 1); $response = ''; $ftp = ftp_ssl_connect('ftps.site.com', 2222, 180); if (!$ftp) { echo 'Connect failed' . "\n"; return -1; } if (!ftp_login($ftp, 'user', 'pass')) { echo 'Login failed' . "\n"; return -1; } ftp_set_option($ftp, FTP_USEPASVADDRESS, false); // added later ftp_pasv($ftp, true); echo 'printing ftp_nlist response: ' . '<br>'; print_r(ftp_nlist($ftp, "/keydealer/")); ftp_close($ftp); echo 'done<br>'; return 0;
原本以为设置ftp_set_option($ftp, FTP_USEPASVADDRESS, false);能解决问题,但没有效果。禁用防火墙后功能恢复正常,请问需要添加什么防火墙规则来解决该问题?
解决方案
这个报错的核心原因是被动模式(PASV)下的FTPS数据连接被防火墙拦截。FTPS使用被动模式时,控制连接(代码里的2222端口)建立后,服务器会开放一段数据端口,客户端需要主动连接这些端口传输目录列表、文件内容等数据,防火墙默认会拦截这类非标准端口的请求。
你需要根据防火墙类型添加对应规则:
1. Linux系统(iptables)
先确认FTP服务器配置的被动模式数据端口范围(比如多数服务器可设置为40000-50000),再执行以下命令:
# 放行FTPS控制端口(对应代码中的2222) iptables -A INPUT -p tcp --dport 2222 -j ACCEPT iptables -A OUTPUT -p tcp --sport 2222 -j ACCEPT # 放行被动模式数据端口范围(示例为40000-50000,需和FTP服务器配置一致) iptables -A INPUT -p tcp --dport 40000:50000 -j ACCEPT iptables -A OUTPUT -p tcp --sport 40000:50000 -j ACCEPT # 保存规则(不同系统命令可能有差异) service iptables save
2. Windows系统防火墙
- 打开Windows Defender防火墙高级设置
- 新建入站规则:
- 规则类型选「端口」,点击下一步
- 选择「TCP」,输入特定本地端口:
2222,40000-50000(替换为你的控制端口和数据端口范围),点击下一步 - 选择「允许连接」,点击下一步
- 勾选适用的网络类型,点击下一步
- 命名规则(如「FTPS端口放行」),完成设置
- 重复上述步骤新建出站规则,确保客户端能发起对这些端口的连接
额外注意事项
- 必须给FTP服务器配置固定的被动模式端口范围(不要用随机端口),否则防火墙无法精准放行。比如vsftpd可在配置文件中设置
pasv_min_port=40000和pasv_max_port=50000 - 代码中已开启被动模式
ftp_pasv($ftp, true);,需确保FTP服务器端也启用了被动模式支持
内容的提问来源于stack exchange,提问作者Scott C Wilson
相关产品推荐
相关产品推荐

