Ruby脚本通过SOCKS 5隧道建立FTPS连接遇阻求助
解决Ruby通过SOCKS5隧道建立FTPS连接的新思路
一、先做基础连通性排查
- 用
curl验证SOCKS5隧道有效性:执行curl --socks5 127.0.0.1:9090 https://目标FTPS服务器地址,确认隧道能正常转发流量 - 核对Ruby脚本与FileZilla的配置细节:确保传输模式(被动/主动)、端口、加密方式(TLS/SSL版本)、登录凭据完全一致,这类细节容易导致连接失败
二、换用库集成式的socksify方案
放弃命令行启动方式,直接在代码中集成socksify配合官方FTPS库:
require 'socksify' require 'net/ftp' # 全局配置SOCKS5代理 TCPSocket.socks_server = '127.0.0.1', 9090 # 初始化FTPS连接(启用TLS) ftp = Net::FTP.new('目标FTPS服务器地址') ftp.passive = true # 和FileZilla保持相同的传输模式 ftp.login('用户名', '密码') # 测试上传/下载操作 ftp.puttextfile('本地文件路径', '远程文件名') ftp.close
如果是隐式FTPS(默认990端口),初始化时改为 Net::FTP.new('目标地址', nil, nil, nil, true),最后一个参数启用隐式TLS
三、针对Windows环境的特殊排查
- 检查Putty隧道监听地址:确保设置为
0.0.0.0:9090而非仅127.0.0.1,部分Windows工具对回环地址的处理存在差异 - 排查防火墙拦截:确认Windows防火墙未阻止Ruby程序访问9090端口及FTPS服务器端口
- 抓包对比差异:用Wireshark监听本地9090端口,对比Ruby脚本与FileZilla的流量包,定位请求差异点
四、手动实现SOCKS5握手(极端场景)
如果库方案均失效,可手动编写SOCKS5握手逻辑后建立FTPS连接:
require 'openssl' # 连接SOCKS5代理 socks_socket = TCPSocket.new('127.0.0.1', 9090) # SOCKS5无认证握手 socks_socket.write([5, 1, 0].pack('C*')) response = socks_socket.read(2) raise "SOCKS握手失败" unless response == [5, 0].pack('C*') # 请求连接FTPS服务器 ftps_host = '目标FTPS服务器地址' ftps_port = 21 # 构造SOCKS连接请求包 socks_socket.write([5, 1, 0, 3, ftps_host.length].pack('C*') + ftps_host + [ftps_port].pack('n')) response = socks_socket.read(10) raise "SOCKS连接请求失败" unless response[1] == 0 # 基于代理socket建立FTPS SSL连接 context = OpenSSL::SSL::SSLContext.new ssl_socket = OpenSSL::SSL::SSLSocket.new(socks_socket, context) ssl_socket.connect # 发送FTPS命令测试 ssl_socket.puts "USER 用户名" puts ssl_socket.gets ssl_socket.puts "PASS 密码" puts ssl_socket.gets ssl_socket.close socks_socket.close
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

