gpt4 book ai didi

go - Golang 中的简单 SSH 端口转发

转载 作者:IT老高 更新时间:2023-10-28 13:09:49 63 4
gpt4 key购买 nike

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

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

我尝试过使用 this example作为起点和this recent test试图理解该怎么做,但现在我有一堆困惑的代码,看起来这实际上是一件非常简单的事情。

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

最佳答案

我终于想出了如何做到这一点,我在 IRC channel 中从 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)
}
}

关于go - Golang 中的简单 SSH 端口转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21417223/

63 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com