doushen9863 2014-01-28 00:48
浏览 219

Golang中的简单SSH端口转发

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! :-)

  • 写回答

4条回答 默认 最新

  • duanjiao7440 2014-02-09 05:00
    关注

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

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题