Golang中简单的SSH端口转发 [英] Simple SSH port forward in Golang

查看:1340
本文介绍了Golang中简单的SSH端口转发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在终端中,我只需运行 ssh -L 9000:localhost:9999 user@server.com ,这就完成了我所需要的。我想用Go来编程。



我试过使用此示例作为起点,这个最近的测试试图了解该做什么,但现在我有一堆混淆混乱的代码,当它看起来像这实际上是一个非常简单的事情。



任何帮助将非常感激! : - )

解决方案

我终于想出了如何做到这一点,我从IRC频道的schmichael得到了一些提示。感谢所有!



编辑:有点解释:
我遇到的问题的一大部分是我没有意识到本地 net.Listener (不只是本地的 net.Conn )需要设置来接收本地请求并创建 net.Conn 在转发字节之前。
另外,同时存在端口转发和反向端口转发,并且我以前没有详细考虑过常规端口转发也发送字节的事实,因此将远程读取器复制到本地作者并不是我所拥有的实施,但它非常需要。
这里试图说明这段代码的实质:


  • 监听本地端口9000.

  • 尝试从本地端口9000读取:( listener.Accept()),

  • 接受连接并返回本地 io.Reader io.Writer

  • 连接连接到远程端口9999,返回一个 io.Reader io.Writer
  • / code>。
  • 将本地 io.Reader 字节连续复制到远程 io.Writer

  • 连续复制远程 io.Reader 字节到本地 io.Writer



以下是代码:

  package main 

//从本地端口9000转到远程端口9999

导入(
io
log
net
golang.org/x/crypto/ssh


var(
username =root
密码=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)
如果err!= nil {
log.Fatalf(ssh.Dial失败:%s,err)
}

//设置sshConn (类型net.Conn)
sshConn,err:= sshClientConn.Dial(tcp,remoteAddrString)

//将localConn.Reader复制到sshConn.Writer
去func( ){
_,err = io.Copy(sshConn,localConn)
if err!= nil {
log.Fatalf(io.Copy failed:%v,err)

$()

//将sshConn.Reader复制到localConn.Writer
去func(){
_,err = io.Copy(localConn ,sshConn)
if err!= nil {
log.Fatalf(io.C opy failed:%v,err)
}
}()
}

func main(){
// Setup SSH config(type * ssh.ClientConfig)
config:=& ssh.ClientConfig {
用户名:username,
认证:[] ssh.AuthMethod {
ssh.Password(password),
},
}

//设置localListener(类型net.Listener)
localListener,err:= net.Listen(tcp,localAddrString)
如果错误!= nil {
log.Fatalf(net.Listen失败:%v,err)
}

用于{
//设置localConn (类型net.Conn)
localConn,err:= localListener.Accept()
if err!= nil {
log.Fatalf(listen.Accept failed:%v,err)

前进(localConn,config)
}
}


I'm trying to create (and later close) a simple TCP port forward over SSH with Go. I'm new to Golang and statically typed languages. (Coming from Ruby.)

In a terminal I would simply run ssh -L 9000:localhost:9999 user@server.com and this accomplishes what I need. I want to do the same, programmatically with Go.

I have tried using this example as a starting point and this recent test to try to understand what to do, but now I have a pile of confusing jumbled code when it seems like this is actually a very simple thing to do.

Any help would be very much appreciated! :-)

解决方案

I finally figured out how to do this, I got hints from schmichael in an IRC channel. Thanks to all!

EDIT: A little explanation: A big part of the problem I was having was that I did not realize a local net.Listener (not just a local net.Conn) needed setup to receive a local request and create the net.Conn before forwarding the bytes. Also, there exist both port forwards and reverse port forwards and I hadn't previously thought in detail about the fact that a regular port forward also sends bytes back, so copying the remote reader to local writer was not something I had implemented, yet it's very much needed. Here is an attempt to relate the essence of what this code does:

  • Listen on local port 9000.
  • Upon attempted read from local port 9000: (listener.Accept()),
  • Accept connection and return a local io.Reader and io.Writer and,
  • Connect to remote server and,
  • Connect to remote port 9999 returning a io.Reader and io.Writer.
  • Continually copy local io.Reader bytes to remote io.Writer,
  • Continually copy remote io.Reader bytes to local io.Writer.

Here is the code:

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)
    }
}

这篇关于Golang中简单的SSH端口转发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆