如何执行简单的SSH x11转发

时间:2019-07-09 13:00:37

标签: go ssh x11 x11-forwarding

我正在尝试在Go中实现ssh x11转发,这参考了Paramiko的源代码,但是效果不佳。

x11-req请求似乎成功,但对于OpenChannel失败。 有没有更好的方法?

https://tools.ietf.org/html/rfc4254#section-6.3.2

完整代码在这里。

https://gist.github.com/blacknon/6e2e6e2c0ebcd64c381925f0e3e86e42

package main

(omit)

func main() {
    // Create sshClientConfig
    sshConfig := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(pass),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }

    // SSH connect.
    client, err := ssh.Dial("tcp", host+":"+port, sshConfig)

    // Create Session
    session, err := client.NewSession()
    defer session.Close()

    // NOTE:
    // x11-req Payload
    payload := x11request{
        SingleConnection: false,
        AuthProtocol:     string("MIT-MAGIC-COOKIE-1"),
        AuthCookie:       string("d92c30482cc3d2de61888961deb74c08"),
        ScreenNumber:     uint32(0),
    }

    // NOTE:
    // send x11-req Request
    ok, err := session.SendRequest("x11-req", true, ssh.Marshal(payload))
    if err == nil && !ok {
        fmt.Println(errors.New("ssh: x11-req failed"))
    }
    fmt.Printf("x11-req: %v\n", ok)
    fmt.Println("-----")

    // x11 OpenChannel (Not working...)
    x11Data := x11channel{
        Host: "localhost",
        Port: uint32(6000),
    }

    sshChan, req, x11err := client.OpenChannel("x11", ssh.Marshal(x11Data))
    fmt.Println(sshChan) // DEBUG
    fmt.Println(req)     // DEBUG
    fmt.Println(x11err)  // DEBUG

    (omit)
}

我添加了sshd侧面调试日志。

sshd[1811]: debug1: server_input_channel_req: channel 0 request x11-req reply 1
sshd[1811]: debug1: session_by_channel: session 0 channel 0
sshd[1811]: debug1: session_input_channel_req: session 0 req x11-req
sshd[1811]: debug1: channel 1: new [X11 inet listener]
sshd[1811]: debug1: channel 2: new [X11 inet listener]
sshd[1811]: debug1: server_input_channel_open: ctype x11 rchan 1 win 2097152 max 32768
sshd[1811]: debug1: server_input_channel_open: failure x11

谢谢大家!多亏了它,我得以安全地实现它。有一个有效的代码。

https://gist.github.com/blacknon/9eca2e2b5462f71474e1101179847d2a

1 个答案:

答案 0 :(得分:0)

// x11 OpenChannel (Not working...)
x11Data := x11channel{
    Host: "localhost",
    Port: uint32(6000),
}

sshChan, req, x11err := client.OpenChannel("x11", ssh.Marshal(x11Data))

这里的根本问题是X11转发通道是从SSH服务器启动到SSH客户端的。您正在尝试打开从客户端到服务器的X11通道。您的服务器不支持此功能,也不是使用X转发的常用方法。

我不是程序员。但是,在查看the documentation之后,在发送x11-req之后,您似乎将调用client.HandleChannelOpen()来接收来自服务器的X11频道请求。

更多背景:为了清楚起见,请先从术语开始。您的程序是 ssh客户端,它连接到 ssh服务器。对于X,服务器是用于控制显示器,键盘和鼠标的程序。 X客户端是xterm和xeyes之类的程序,它们连接到服务器以显示窗口并执行类似的操作。

当您想通过SSH转发X11时,ssh客户端会将X11请求发送到ssh服务器。这告诉服务器客户端希望X11转发该连接。服务器将执行一些设置,并打开一个TCP侦听端口以接收来自X客户端的连接。

当X客户端连接到ssh服务器的X11侦听端口时,ssh服务器将打开一个返回ssh客户端的通道。 ssh客户端将连接到本地X服务器,并且ssh客户端和ssh服务器将在X服务器(对ssh客户端主机本地)和X客户端(对ssh服务器主机本地)之间中继数据。每个通道只处理一个X客户端。

因此,您这样的程序必须向服务器发送请求,以表明您的程序希望通过ssh连接转发X11。当X客户端尝试使用转发的X11服务时,实际的x11通道将根据需要从ssh服务器打开到ssh客户端。