【问题标题】:Simple SSH port forward in GolangGolang 中的简单 SSH 端口转发
【发布时间】:2018-05-20 14:39:17
【问题描述】:

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

在终端中,我只需运行 ssh -L 9000:localhost:9999 user@server.com 即可完成我所需要的。我想用 Go 以编程方式做同样的事情。

我曾尝试使用this example 作为起点并尝试使用this recent test 来尝试理解该做什么,但现在我有一堆令人困惑的混乱代码,而这看起来实际上是一件非常简单的事情。

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

【问题讨论】:

  • 你有什么乱七八糟的代码?
  • 感谢 MichaelT,混乱的一堆已成功删除并重新创建到以下答案中。感谢您愿意提供帮助!
  • 您是否认为(在下面的回答中)您可以完成获得最终代码的步骤,根本原因是什么以及如何解决?
  • 我希望这些编辑有所帮助。发生了如此多的变化,一次又一次的变化,很难安排我是如何到达那里的。 :) 再次感谢。

标签: go


【解决方案1】:

我终于想出了如何做到这一点,我在 IRC 频道中从 schmichael 那里得到了提示。谢谢大家!

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

  • 监听本地端口 9000。
  • 尝试从本地端口 9000 读取时:(listener.Accept()),
  • 接受连接并返回本地io.Readerio.Writer 和,
  • 连接到远程服务器,
  • 连接到远程端口 9999,返回 io.Readerio.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 -D
  • 我希望我能帮助你那里的朋友,但我对 SOCKS 和所有东西还不够熟悉。 This 可能会帮助你。祝你好运,如果你得到它,请告诉我!
  • 请注意 - go.grypto 包现在托管在 golang.org/x/crypto/ssh,此外,为了使这个出色的示例能够正常工作(感谢 @damick!),您需要考虑交换 @ 987654337@ 和 ssh.AuthMethod,根据包 API 的更改。
【解决方案2】:

我已使用您的 (damick) 示例代码构建了一个小型开源工具:SSHTunnel https://github.com/SommerEngineering/SSHTunnel

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

最好的问候, 托尔斯滕。

【讨论】:

    【解决方案3】:

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

    核心代码类似于damick的回答。

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

      Dial 启动从远程主机到 addr 的连接。结果连接的 LocalAddr() 和 RemoteAddr() 为零。

    4. 如果您想为 SOCKS 代理服务器提供服务,请使用 Client.Dial 连接到远程服务器。

    【讨论】:

    • 我已经成功安装了 mallory,但是当我运行命令:mallory -engine=ssh -remote=ssh://root:123456789abc@104.207.140.29:22 时,我遇到了以下错误:提供但未定义的标志:-engine mallory 的用法:-config 字符串配置文件(默认为“$HOME/.config/mallory.json”)-reload 发送信号以重新加载配置文件 -suffix string 打印给定域的公共后缀
    • 希望得到您的帮助
    • 我可以用用户名和密码连接吗?谢谢
    【解决方案4】:

    我写了一个工具,叫gosshtool,用这个工具,你可以很容易的用Go创建一个简单的通过SSH转发的TCP端口。https://github.com/scottkiss/gosshtool

    我使用这个工具实现了一个端口转发服务器示例项目: https://github.com/scottkiss/gooverssh

    【讨论】:

      猜你喜欢
      • 2017-01-30
      • 2011-02-19
      • 1970-01-01
      • 1970-01-01
      • 2011-03-09
      • 2018-10-24
      • 2012-03-20
      • 2021-07-01
      • 1970-01-01
      相关资源
      最近更新 更多