Golang中的简单SSH端口转发

Golang中的简单SSH端口转发,go,Go,我正在尝试使用Go通过SSH创建(稍后关闭)一个简单的TCP端口转发。我不熟悉Golang和静态类型语言。(来自Ruby。) 在终端中,我只需运行ssh-l9000:localhost:9999user@server.com这就满足了我的需要。我想用Go以编程的方式做同样的事情 我试着用它作为起点,试着理解该做什么,但现在我有一堆混乱的代码,而这看起来实际上是一件非常简单的事情 任何帮助都将不胜感激!:-) 我终于想出了这个方法,我从一个IRC频道的schmichael那里得到了一些提示。谢谢大

我正在尝试使用Go通过SSH创建(稍后关闭)一个简单的TCP端口转发。我不熟悉Golang和静态类型语言。(来自Ruby。)

在终端中,我只需运行ssh-l9000:localhost:9999user@server.com这就满足了我的需要。我想用Go以编程的方式做同样的事情

我试着用它作为起点,试着理解该做什么,但现在我有一堆混乱的代码,而这看起来实际上是一件非常简单的事情


任何帮助都将不胜感激!:-)

我终于想出了这个方法,我从一个IRC频道的schmichael那里得到了一些提示。谢谢大家

编辑:一点解释: 我遇到的大部分问题是,我没有意识到本地
net.Listener
(不仅仅是本地
net.Conn
)需要设置来接收本地请求并在转发字节之前创建
net.Conn
。 此外,端口转发和反向端口转发都存在,我以前没有详细考虑常规端口转发也会发送字节,因此将远程读卡器复制到本地写卡器不是我实现的,但这是非常必要的。 下面是一个尝试,以说明此代码的本质:

  • 在本地端口9000上侦听
  • 尝试从本地端口9000读取时:(
    listener.Accept()
  • 接受连接并返回本地
    io.Reader
    io.Writer
  • 连接到远程服务器并
  • 连接到远程端口9999,返回
    io.Reader
    io.Writer
  • 持续将本地
    io.Reader
    字节复制到远程
    io.Writer
  • 持续将远程
    io.Reader
    字节复制到本地
    io.Writer
代码如下:

package main

// Forward from local port 9000 to remote port 9999

import (
    "io"
    "log"
    "net"
    "golang.org/x/crypto/ssh"
)

var (
    username         = "root"
    password         = "password"
    serverAddrString = "192.168.1.100:22"
    localAddrString  = "localhost:9000"
    remoteAddrString = "localhost:9999"
)

func forward(localConn net.Conn, config *ssh.ClientConfig) {
    // Setup sshClientConn (type *ssh.ClientConn)
    sshClientConn, err := ssh.Dial("tcp", serverAddrString, config)
    if err != nil {
        log.Fatalf("ssh.Dial failed: %s", err)
    }

    // Setup sshConn (type net.Conn)
    sshConn, err := sshClientConn.Dial("tcp", remoteAddrString)

    // Copy localConn.Reader to sshConn.Writer
    go func() {
        _, err = io.Copy(sshConn, localConn)
        if err != nil {
            log.Fatalf("io.Copy failed: %v", err)
        }
    }()

    // Copy sshConn.Reader to localConn.Writer
    go func() {
        _, err = io.Copy(localConn, sshConn)
        if err != nil {
            log.Fatalf("io.Copy failed: %v", err)
        }
    }()
}

func main() {
    // Setup SSH config (type *ssh.ClientConfig)
    config := &ssh.ClientConfig{
        User: username,
        Auth: []ssh.AuthMethod{
            ssh.Password(password),
        },
    }

    // Setup localListener (type net.Listener)
    localListener, err := net.Listen("tcp", localAddrString)
    if err != nil {
        log.Fatalf("net.Listen failed: %v", err)
    }

    for {
        // Setup localConn (type net.Conn)
        localConn, err := localListener.Accept()
        if err != nil {
            log.Fatalf("listen.Accept failed: %v", err)
        }
        go forward(localConn, config)
    }
}

我已经完成了一个简单的SSH端口转发工具,名为。 它提供HTTP代理而不是SOCKS代理,这与ssh-D非常相似

核心代码与damick的答案类似

  • 创建客户端配置
  • ssh.Dial
    到远程ssh服务器,并返回
    客户端
  • 现在您可以使用
    Client.Dial
    转发任何您喜欢的内容

    拨号从远程主机启动到addr的连接。结果连接的LocalAddr()和RemoteAddr()为零
  • 如果要为SOCKS代理服务器提供服务,请使用
    Client.Dial
    连接到远程服务器
  • 我用你的(damick)示例代码构建了一个小型开源工具:SSHTunnel

    因此,任何人都可以在GitHub上免费获得该代码:请随时将其用于学习目的或其他任何目的:)我提到了您的昵称,并与此问题链接

    致以最良好的祝愿,
    Thorsten.

    我编写了一个名为gosstool的工具,通过这个工具,您可以轻松地使用Go通过SSH创建一个简单的TCP端口转发

    我使用此工具实现了一个端口转发服务器示例项目:

    您有多少乱码?感谢MichaelT,在下面的答案中,已成功删除并重新创建了乱码。谢谢你的帮助!你认为(在你下面的回答中)你能完成最终代码所需的步骤吗?根本原因是什么以及如何解决?我希望这些编辑能有所帮助。有这么多的变化,又一次的变化,很难规划我是如何到达那里的再次感谢。你能告诉我如何使动态转发工作吗?像宋承宪一样,我希望我能在那里帮助你,朋友,但我对袜子和其他东西还不够熟悉。也许对你有帮助。祝你好运,如果你得到它,请告诉我!请注意,
    go.grypto
    包现在托管在
    golang.org/x/crypto/ssh
    ,另外,为了让这个优秀的示例发挥作用(谢谢@damick!),您需要考虑将
    ssh.ClientAuth
    ssh.AuthMethod
    交换,根据对包API的更改,我已经成功安装了mallory,但是当我运行命令:mallory-engine=ssh-remote时=ssh://root:123456789abc@104.207.140.29:22,我遇到了以下错误:提供了标记,但未定义:-mallory的引擎用法:-配置字符串配置文件(默认值“$HOME/.config/mallory.json”)-重新加载发送信号以重新加载配置文件-后缀字符串打印给定域的pulbic后缀希望您的帮助我可以连接用户和密码。感谢