AWS Lambda中ftplib RETR小文件卡住,PORT地址异常求助
问题分析与解决方案
核心原因
AWS Lambda执行环境采用NAT网络架构,默认情况下ftplib在主动模式(PORT模式)下会自动绑定到本地链路本地地址(如169.254.76.1),这个地址无法被工业HMI控制面板访问——因为HMI需要主动连接PORT命令指定的IP:端口来传输数据,而链路本地地址属于不可路由的内网地址,最终导致下载超时卡住。
本地测试正常是因为你的机器有可被HMI访问的局域网IP,ftplib会自动使用这个IP构造PORT命令。
解决方案:自定义FTPLib类强制指定可路由IP
要解决这个问题,需要重写ftplib.FTP的makeport方法,让它使用Lambda执行环境的可路由IP(公网出口IP或VPC私有IP,取决于HMI的网络可达性)来构造PORT命令。
代码示例
场景1:HMI可访问公网(Lambda使用公网NAT)
import ftplib import socket import requests class HMI_FTP(ftplib.FTP): def makeport(self): # 获取Lambda公网出口IP(通过AWS官方检测服务) public_ip = requests.get('http://checkip.amazonaws.com').text.strip() # 创建监听socket,绑定随机端口 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('', 0)) sock.listen(1) port = sock.getsockname()[1] # 构造PORT命令格式:将IP拆分为四段,端口拆分为高低字节 ip_segments = public_ip.split('.') port_high = port // 256 port_low = port % 256 self.sendport(*ip_segments, port_high, port_low) return sock # 使用自定义类连接HMI并下载文件 with HMI_FTP("HMI_FTP_HOST") as ftp: ftp.login("USERNAME", "PASSWORD") with open("/tmp/downloaded_file", "wb") as f: ftp.retrbinary("RETR target_file.txt", f.write)
场景2:HMI与Lambda在同一VPC/可路由私有网络
如果HMI仅能访问私有网络,替换公网IP获取逻辑为VPC私有IP:
# 替换makeport中的IP获取部分 private_ip = requests.get('http://169.254.169.254/latest/meta-data/local-ipv4').text.strip()
必要的网络配置检查
- 安全组规则:
- Lambda所在安全组需允许入站:HMI的IP/子网访问所有TCP端口(因为主动模式的传输端口是随机分配的)
- Lambda所在安全组需允许出站:访问HMI的FTP端口(默认21)
- 网络可达性:
- 若使用VPC,确保HMI所在网络与Lambda的VPC通过对等连接、Direct Connect等方式打通
- 若使用公网,确保HMI的防火墙/网关允许访问Lambda的公网出口IP
无关操作说明
你之前尝试的下载到/tmp目录、添加SITE CHMOD命令无法解决问题,因为核心故障是网络层面的PORT地址不可达,这些操作不影响FTP主动模式的网络握手流程。
内容的提问来源于stack exchange,提问作者Shenanigator
相关产品推荐
相关产品推荐

