如何使用 Ruby 进行动态端口转发

Posted

技术标签:

【中文标题】如何使用 Ruby 进行动态端口转发【英文标题】:How to do dynamic port forwarding using Ruby 【发布时间】:2019-11-22 13:49:17 【问题描述】:

如何在 Ruby 上进行 SSH 动态端口转发?

我尝试使用诸如“net/ssh/socks”和“net/ssh/gateway”之类的 gem,但看起来它们已经过时了,因为我什至不需要它们。

我需要做的就是运行这个 shell 命令

ssh -D 5555 user@host -f -N

并接收该进程的PID。

我也尝试使用Kernel#systemKernel#spawn

例如:

pid = spawn("ssh -D 5555 user@host -f -N")
Process.wait pid

这对我来说很好,但是返回的 PID 总是比启动的进程的实际 PID 少 3 个单位。例如返回的PID为1555,真实的PID为1558

另一个问题:为什么 PID 的差异总是 3,是否还有其他差异?我可以可靠地使用pid + 3 吗?

【问题讨论】:

如何确定“真实PID”?我无法重现此 PID 问题,因为 SSH 在运行时不应分叉。如果你这样做pid = spawn "sleep 300" 会发生什么?那你得到正确的PID了吗?另外:你如何检查正确的 PID,你正在运行什么命令。最好将此信息添加到问题中。 【参考方案1】:

使用 SSH 二进制文件

您正在使用-f (fork) 运行 SSH。在 Ruby 中,Kernel.spawn 会自动将进程分叉到后台,因此您不需要使用-f。如果使用-f会造成双叉的情况,这就是PID异常的原因。

这应该足以让它工作:

pid = spawn("ssh -N -D 5555 user@host")

将 Net::SSH 与 Net::SSH::Socks 结合使用

如果您想使用net-ssh-socks,则必须手动克隆存储库,因为 Rubygems 版本尚未针对最新的 Net::SSH 进行更新。

git clone https://github.com/cristianbica/net-ssh-socks

假设您克隆到运行脚本所在的同一文件夹中,那么您的 Ruby 代码将如下所示:

$:.push('net-ssh-socks/lib')  # Add the cloned repo to load path
require 'net/ssh/socks'

ssh = Net::SSH.start('host', 'user')
ssh.forward.socks(5555)
ssh.loop  true 

【讨论】:

谢谢!这解决了 PID 的问题。所以在 Ruby 中,这似乎是动态端口转发的最合适的选项。 好像是这样。 net-ssh-socks gem 仅与 Net::SSH 2.0.24(当前版本 5.x.x)兼容。如果您愿意使用该版本(例如在 Bundler 的帮助下),那么它可能也可以工作。 Daniel 看到我的编辑。我添加了另一个似乎也适用于最新 Net::SSH 版本的选项。 非常感谢!我会在测试后立即给您反馈。

以上是关于如何使用 Ruby 进行动态端口转发的主要内容,如果未能解决你的问题,请参考以下文章

我是如何逃过所有杀软进行内网端口转发的

如何使用花生壳解析动态IP

CentOS如何转发所有端口到内网主机(和路由器DMZ一样),包括来源IP和ICMP?

关于端口映射的问题(如何将端口转发给域名)?

ssh动态端口转发

如何修复监听端口 80 的远程端口转发失败