如何在Python中通过SOCKS5代理实现FTPS文件获取?
通过SOCKS5代理访问FTPS服务器的可行方案
这个问题确实挺棘手的——毕竟Python标准库的FTP相关工具和代理工具好像天生不对付,但其实我们有办法把它们捏合在一起!下面给你两种可行的实现思路,亲测有效:
方案一:改造标准库ftplib的FTP_TLS类,结合PySocks
核心思路是:先用PySocks创建一个经过SOCKS5代理的socket,然后把这个socket替换掉ftplib.FTP_TLS默认的socket,这样就能在保持FTPS加密的同时通过代理访问服务器。
import socks from ftplib import FTP_TLS # 代理配置 SOCKS5_PROXY_HOST = "你的SOCKS5代理主机" SOCKS5_PROXY_PORT = 1080 # 替换成你的代理端口 SOCKS5_PROXY_USER = "代理用户名(如果有的话)" SOCKS5_PROXY_PW = "代理密码(如果有的话)" # FTPS服务器配置 FTPS_HOST = "你的FTPS服务器地址" FTPS_PORT = 990 # 隐式FTPS默认端口,显式模式用21 FTPS_USER = "FTPS用户名" FTPS_PW = "FTPS密码" # 1. 创建带SOCKS5代理的socket s = socks.socksocket() s.set_proxy( socks.SOCKS5, SOCKS5_PROXY_HOST, SOCKS5_PROXY_PORT, username=SOCKS5_PROXY_USER, password=SOCKS5_PROXY_PW ) # 2. 用这个socket连接FTPS服务器 s.connect((FTPS_HOST, FTPS_PORT)) # 3. 初始化FTP_TLS并替换默认socket ftp_tls = FTP_TLS() ftp_tls.sock = s # 4. 登录并启用数据通道加密(显式模式先login再调用prot_p(),隐式模式可以直接login) ftp_tls.login(FTPS_USER, FTPS_PW) ftp_tls.prot_p() # 开启数据传输加密,推荐启用 # 5. 下载文件示例 remote_file = "/服务器上的文件路径/xxx.txt" local_file = "/本地保存路径/xxx.txt" with open(local_file, "wb") as f: ftp_tls.retrbinary(f"RETR {remote_file}", f.write) # 6. 关闭连接 ftp_tls.quit()
注意事项:
- 区分FTPS的隐式模式(端口990,连接瞬间就加密)和显式模式(端口21,先建立明文连接,再通过
AUTH TLS切换加密)。如果是显式模式,登录后记得调用ftp_tls.prot_p()开启数据通道加密。 - 如果服务器用的是自签名证书,需要跳过证书验证(生产环境不推荐),可以这样初始化FTP_TLS:
import ssl ftp_tls = FTP_TLS(context=ssl._create_unverified_context())
方案二:用ftputil简化操作(更优雅的封装)
如果你觉得手动替换socket太麻烦,可以用ftputil这个第三方库——它对ftplib做了更友好的封装,还支持自定义socket工厂,能轻松结合PySocks实现代理访问。
首先需要安装ftputil:
pip install ftputil
然后是实现代码:
import socks import ftputil from ftplib import FTP_TLS # 代理配置(同上) SOCKS5_PROXY_HOST = "你的SOCKS5代理主机" SOCKS5_PROXY_PORT = 1080 SOCKS5_PROXY_USER = "代理用户名" SOCKS5_PROXY_PW = "代理密码" # FTPS服务器配置(同上) FTPS_HOST = "你的FTPS服务器地址" FTPS_USER = "FTPS用户名" FTPS_PW = "FTPS密码" FTPS_PORT = 990 # 自定义socket工厂:返回经过SOCKS5代理的socket def create_socks_socket(host, port): s = socks.socksocket() s.set_proxy( socks.SOCKS5, SOCKS5_PROXY_HOST, SOCKS5_PROXY_PORT, username=SOCKS5_PROXY_USER, password=SOCKS5_PROXY_PW ) s.connect((host, port)) return s # 使用ftputil的FTP_TLS上下文管理器 with ftputil.FTP_TLS( FTPS_HOST, user=FTPS_USER, password=FTPS_PW, port=FTPS_PORT, # 传入自定义的socket工厂 session_factory=lambda: FTP_TLS(socket_factory=create_socks_socket) ) as ftp: # 下载文件,用法和操作本地文件几乎一样 ftp.download("/服务器文件路径/xxx.txt", "/本地保存路径/xxx.txt")
优点:
- ftputil提供了类文件系统的API,操作FTP服务器更直观(比如
ftp.listdir()、ftp.mkdir()等)。 - 上下文管理器自动处理连接的开闭,不用手动调用
quit()。
内容的提问来源于stack exchange,提问作者Zu Jiry
相关产品推荐
相关产品推荐

