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

基于pyftpdlib搭建的FTP服务器无法外网访问求助

解决NAT环境下pyftpdlib FTP服务器公网访问问题

问题背景

我基于pyftpdlib官方文档写了FTP服务器代码,本地用私有IP或者localhost能正常访问,但用公网IP从外网设备连接就超时。目前是连的手机热点(处于NAT环境),已经给21端口加了防火墙允许规则,但没用,试了网上同类方案也没解决。想实现外网通过公网IP访问,同时搞清楚不同场景下的IP使用规则。

现有代码与运行日志

服务器代码

import os
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer

def main():
    # Instantiate a dummy authorizer for managing 'virtual' users
    authorizer = DummyAuthorizer()
    # Define a new user having full r/w permissions and a read-only
    # anonymous user
    authorizer.add_user('user', '12345', '.', perm='elradfmwMT')
    authorizer.add_anonymous(os.getcwd())

    # Instantiate FTP handler class
    handler = FTPHandler
    handler.authorizer = authorizer

    # Define a customized banner (string returned when client connects)
    handler.banner = "pyftpdlib based ftpd ready."

    # Specify a masquerade address and the range of ports to use for
    # passive connections. Decomment in case you're behind a NAT.
    handler.masquerade_address = 'My Public IP checked online'
    handler.passive_ports = range(20, 65535)

    # Instantiate FTP server class and listen on 0.0.0.0:2121
    address = ('0.0.0.0', 21)
    server = FTPServer(address, handler)

    # set a limit for connections
    server.max_cons = 256
    server.max_cons_per_ip = 5

    # start ftp server
    server.serve_forever()

if __name__ == '__main__':
    main()

运行日志

[I 2020-05-11 20:27:13] concurrency model: async
[I 2020-05-11 20:27:13] masquerade (NAT) address: X.X.X.X
[I 2020-05-11 20:27:13] passive ports: 20->65534
[I 2020-05-11 20:27:13] >>> starting FTP server on 0.0.0.0:21, pid=9072 <<<
[I 2020-05-11 20:28:07] 127.0.0.1:5054-[] FTP session opened (connect)
[I 2020-05-11 20:28:07] 127.0.0.1:5054-[anonymous] USER 'anonymous' logged in.
[I 2020-05-11 20:28:07] 127.0.0.1:5054-[anonymous] CWD C:\Users\Dell\Desktop\ftp_server 250

问题分析

出现公网访问超时的核心原因主要有这几点:

  1. 手机热点的CGNAT限制:大部分手机运营商提供的是共享公网IP(Carrier-Grade NAT),你的设备并没有独立的公网IP,外网直接访问这个公网IP无法定位到你的设备。
  2. 运营商端口屏蔽:很多运营商会默认屏蔽21这类标准FTP端口,避免用户搭建公共服务。
  3. 被动模式端口未正确转发:FTP被动模式需要开放一段端口范围,你代码里设置了20到65535的大范围,但防火墙没开放这么多端口,而且手机热点一般不支持端口转发,导致外网无法连接被动端口。
  4. 防火墙/安全软件拦截:除了入站规则,出站规则或者第三方安全软件可能拦截了FTP流量。

分步解决方案

1. 更换非标准FTP端口

先避开运营商屏蔽的21端口,修改代码里的监听端口为非标准端口(比如2121):

address = ('0.0.0.0', 2121)

同时在系统防火墙里添加2121端口的入站允许规则。

2. 缩小被动端口范围

代码里的被动端口范围太大,既不安全也难以配置,改成一个小范围(比如50000-50100):

handler.passive_ports = range(50000, 50100)

然后在防火墙里添加这个端口范围的入站允许规则。

3. 解决CGNAT问题(核心)

因为手机热点是CGNAT环境,没有独立公网IP,需要用内网穿透工具来实现外网访问,比如frp、ngrok这类工具:

  • 部署一个内网穿透客户端,将你的2121端口和50000-50100端口映射到公网服务器的对应端口。
  • 外网设备使用穿透工具提供的公网IP+映射端口来连接FTP服务器。

如果能换成有独立公网IP的宽带网络,那可以在路由器上做端口转发:

  • 把路由器的2121端口转发到你的设备私有IP的2121端口。
  • 把路由器的50000-50100端口范围转发到你的设备私有IP的对应端口范围。

4. 检查防火墙与安全软件

  • 确认系统防火墙的入站规则不仅开放了2121和被动端口范围,出站规则也没有限制FTP相关流量。
  • 暂时关闭Windows Defender或者第三方杀毒软件,测试是否能连接,能的话把pyftpdlib程序加入信任列表。

不同场景IP使用说明

  • 本机访问:用localhost或者127.0.0.1,直接连接本地服务。
  • 局域网内其他设备访问:用你的设备私有IP(比如192.168.43.x,手机热点的局域网段一般是这个)。
  • 外网访问(有独立公网IP):用你的公网IP,配合路由器端口转发和防火墙规则。
  • 外网访问(CGNAT环境):用内网穿透工具提供的公网IP+映射端口,或者工具分配的域名。

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

火山引擎 最新活动