You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python ftplib主动模式下指定外部IP地址?

解决Python FTP主动模式下指定外部IP的问题

在FTP主动模式下,服务器需要主动发起与客户端数据端口的连接。如果你的机器处于NAT网络后,服务器只能拿到你的内网IP,无法建立数据连接,这就是你执行ftp.dir()时超时的原因——WinSCP/FileZilla里的“外部IP”设置就是用来告诉服务器你的公网IP,让它能正确连接到你。

Python标准库的ftplib没有直接提供设置外部IP的接口,但可以通过扩展FTP类来实现:

自定义FTP类指定外部IP

from ftplib import FTP
import socket

class FTPWithExternalIP(FTP):
    def __init__(self, external_ip, *args, **kwargs):
        self.external_ip = external_ip
        super().__init__(*args, **kwargs)

    def makeport(self):
        # 创建数据套接字,绑定本地任意可用端口
        data_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        data_sock.bind(('', 0))
        data_sock.listen(1)
        
        # 提取本地端口并转换为FTP协议要求的格式
        local_port = data_sock.getsockname()[1]
        ip_segments = list(map(int, self.external_ip.split('.')))
        port_segments = [local_port >> 8 & 0xff, local_port & 0xff]
        ftp_port_str = ','.join(map(str, ip_segments + port_segments))
        
        # 向服务器发送PORT命令,告知公网IP和数据端口
        self.sendport(ftp_port_str)
        return data_sock

使用方式

把你的公网IP传入自定义类,按正常流程初始化、连接、登录即可:

# 替换成你的实际信息
EXTERNAL_IP = "123.123.123.123"
FTP_SERVER = "ftp.example.com"
USERNAME = "your_username"
PASSWORD = "your_password"

ftp = FTPWithExternalIP(EXTERNAL_IP)
ftp.connect(FTP_SERVER, 21)
ftp.login(USERNAME, PASSWORD)
ftp.setpasv(False)  # 启用主动模式

# 现在可以正常执行目录操作
ftp.dir()

ftp.quit()

关键注意事项

  • 确认你的公网IP正确:可以通过公网IP查询工具获取
  • 防火墙配置:确保本地防火墙允许FTP数据连接入站(主动模式下服务器会连接你随机的高位端口,若要固定端口,可修改bind(('', 0))为bind(('', 固定端口)),同时在NAT设备上配置端口转发)
  • NAT端口转发:如果你的机器在路由器后,需要在路由器上把FTP数据端口(或指定的固定端口)转发到你的内网IP

你之前尝试的ftp.connect指定源地址,只是绑定本地网卡的IP,并没有把公网IP告知服务器;而忽略返回IP的方案通常针对被动模式,主动模式下不适用。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 03:27:27