Ruby中Socket.tcp客户端通过指定机器代理的实现问询
在Sidekiq Worker里单独代理Socket连接的完美方案
嘿,刚好我之前踩过类似的坑,你提到的Net::SSH完全能解决你的问题——而且刚好能实现「只代理当前Worker代码,不影响服务器其他进程」的需求,比你之前试的ruby-proxifier更贴合场景。
核心思路:用Net::SSH创建临时隔离的本地代理
Net::SSH支持本地动态SOCKS转发,简单来说就是在你的Worker进程里临时开一个小代理,Worker跑完这个代理就自动消失,完全不会干扰服务器上的其他代码。结合ruby-proxifier的块级代理,就能精准控制只有Worker里的Socket连接走代理。
步骤1:先搞定依赖
确保Gemfile里有这两个包:
gem 'net-ssh' gem 'ruby-proxifier' # 如果你用SOCKS动态代理的话需要它
然后跑bundle install就行。
步骤2:Sidekiq Worker的具体实现
我给你写个完整的Worker示例,注释都标清楚了:
class ProxySocketWorker include Sidekiq::Worker def perform(target_host, target_port, proxy_host, proxy_user, proxy_key_path) # 先通过Net::SSH连到你的代理机器,建立动态端口转发 Net::SSH.start(proxy_host, proxy_user, keys: [proxy_key_path]) do |ssh| # 在本地开一个1080端口作为临时SOCKS代理(怕冲突的话可以用0让系统随机分配) local_socks_port = ssh.forward.local(1080, '0.0.0.0', 0, handler: Net::SSH::Proxy::SOCKS5.new('localhost', 1080)) # 用ruby-proxifier的块语法,只有这个块里的代码会走代理! Proxifier::Proxy("socks5://localhost:#{local_socks_port}") do # 这里就是你的Socket逻辑,完全走代理 socket = Socket.tcp(target_host, target_port, connect_timeout: 10) # 比如发送数据、接收响应之类的操作... socket.write("Hello via proxy!\n") response = socket.gets puts response socket.close end end # 到这里,SSH连接关闭,临时代理也没了,其他代码不受影响 end end
关键细节要注意
- 完全隔离:这个临时代理是绑定在当前Worker线程的,Worker执行完,SSH连接断开,代理直接销毁,服务器上其他进程的网络请求该怎么走还是怎么走。
- 块级代理控制:ruby-proxifier的
Proxifier::Proxy() do ... end是局部生效的,块外的代码不会被代理,完美满足你只代理Worker代码的需求。 - 端口冲突解决:如果1080端口可能被占用,把
1080换成0,系统会自动分配一个空闲端口,然后用local_socks_port变量拿到这个端口号就行。
更轻量的替代方案(不用ruby-proxifier)
如果你只是要连固定的目标主机和端口,完全可以不用ruby-proxifier,直接用Net::SSH的静态端口转发:
class ProxySocketWorker include Sidekiq::Worker def perform(target_host, target_port, proxy_host, proxy_user, proxy_key_path) Net::SSH.start(proxy_host, proxy_user, keys: [proxy_key_path]) do |ssh| # 把本地9999端口转发到目标机器的target_port ssh.forward.local(9999, target_host, target_port) # 直接连本地9999,流量会自动通过代理机器转发到目标主机 socket = Socket.tcp('localhost', 9999, connect_timeout: 10) # 后续操作... end end end
这个方案更简单,没有额外依赖,适合固定目标的场景。
内容的提问来源于stack exchange,提问作者brandonhilkert
相关产品推荐
相关产品推荐

