使用 GO 的 SSH 反向隧道
SSH Reverse Tunnel with GO
我正在尝试编写一个可以帮助绕过防火墙/Nat 问题的服务器/客户端。
我注意到 SSH 已经内置了对执行此操作的支持。
(http://rustyrazorblade.com/2010/03/ssh-reverse-tunnel-to-access-box-behind-firewall/)
我尝试了几个不同的 SSH 示例,none 似乎可以正常工作。我发现一个项目说它实现了远程端口转发 -> https://godoc.org/dev.justinjudd.org/justin/easyssh
服务器说它正在侦听连接,但我无法通过 SSH 从服务器计算机连接到客户端计算机。 (远程机器上的 ssh localhost 8080 应该转发到客户端机器。
客户端 ->
package main
import (
"log"
"dev.justinjudd.org/justin/easyssh"
"golang.org/x/crypto/ssh"
)
func main() {
config := &ssh.ClientConfig{
User: "test",
Auth: []ssh.AuthMethod{
ssh.Password("test"),
},
}
conn, err := easyssh.Dial("tcp", "*SSH-SERVER*:22", config)
if err != nil {
log.Fatalf("unable to connect: %s", err)
}
defer conn.Close()
err = conn.RemoteForward("0.0.0.0:8080", "127.0.0.1:22")
if err != nil {
log.Fatalf("unable to forward local port: %s", err)
}
}
服务器 ->
package main
import (
"fmt"
"io/ioutil"
"log"
"dev.justinjudd.org/justin/easyssh"
"golang.org/x/crypto/ssh"
)
func main() {
privateBytes, err := ioutil.ReadFile("id_rsa")
if err != nil {
log.Fatal("Failed to load private key (./id_rsa)")
}
private, err := ssh.ParsePrivateKey(privateBytes)
if err != nil {
log.Fatal("Failed to parse private key")
}
config := &ssh.ServerConfig{
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
if c.User() == "test" && string(pass) == "test" {
log.Printf("User logged in: %s", c.User())
return nil, nil
}
return nil, fmt.Errorf("password rejected for %s", c.User())
},
}
config.AddHostKey(private)
easyssh.HandleChannel(easyssh.SessionRequest, easyssh.SessionHandler())
easyssh.HandleChannel(easyssh.DirectForwardRequest, easyssh.DirectPortForwardHandler())
easyssh.HandleRequestFunc(easyssh.RemoteForwardRequest, easyssh.TCPIPForwardRequest)
easyssh.ListenAndServe(":22", config, nil)
}
我不确定您是否了解 SSH 隧道在您的代码中的工作原理。
您需要与远程(服务器)建立 SSH 连接。
然后设置 SSH 隧道,以便使用 SSH 连接将本地 TCP:8080 端口转发到远程服务器 TCP:8080 端口。实际8080端口可以通过防火墙关闭。
您可以使用 SSH 从您的客户端连接到您的服务器吗?
您需要检查 localhost:8080 端口并且您需要确保您的服务器 8080 端口也被某些应用程序监听。
看看here一些例子和理论。
我在 easyssh 中发现了一个与远程端口转发相关的错误:
https://dev.justinjudd.org/justin/easyssh/src/master/tcpip.go#L107
ssh.DiscardRequests(reqs)
应该是运行分开的goroutine
,否则下一次数据传输将不会执行。
我正在尝试编写一个可以帮助绕过防火墙/Nat 问题的服务器/客户端。
我注意到 SSH 已经内置了对执行此操作的支持。 (http://rustyrazorblade.com/2010/03/ssh-reverse-tunnel-to-access-box-behind-firewall/)
我尝试了几个不同的 SSH 示例,none 似乎可以正常工作。我发现一个项目说它实现了远程端口转发 -> https://godoc.org/dev.justinjudd.org/justin/easyssh
服务器说它正在侦听连接,但我无法通过 SSH 从服务器计算机连接到客户端计算机。 (远程机器上的 ssh localhost 8080 应该转发到客户端机器。
客户端 ->
package main
import (
"log"
"dev.justinjudd.org/justin/easyssh"
"golang.org/x/crypto/ssh"
)
func main() {
config := &ssh.ClientConfig{
User: "test",
Auth: []ssh.AuthMethod{
ssh.Password("test"),
},
}
conn, err := easyssh.Dial("tcp", "*SSH-SERVER*:22", config)
if err != nil {
log.Fatalf("unable to connect: %s", err)
}
defer conn.Close()
err = conn.RemoteForward("0.0.0.0:8080", "127.0.0.1:22")
if err != nil {
log.Fatalf("unable to forward local port: %s", err)
}
}
服务器 ->
package main
import (
"fmt"
"io/ioutil"
"log"
"dev.justinjudd.org/justin/easyssh"
"golang.org/x/crypto/ssh"
)
func main() {
privateBytes, err := ioutil.ReadFile("id_rsa")
if err != nil {
log.Fatal("Failed to load private key (./id_rsa)")
}
private, err := ssh.ParsePrivateKey(privateBytes)
if err != nil {
log.Fatal("Failed to parse private key")
}
config := &ssh.ServerConfig{
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
if c.User() == "test" && string(pass) == "test" {
log.Printf("User logged in: %s", c.User())
return nil, nil
}
return nil, fmt.Errorf("password rejected for %s", c.User())
},
}
config.AddHostKey(private)
easyssh.HandleChannel(easyssh.SessionRequest, easyssh.SessionHandler())
easyssh.HandleChannel(easyssh.DirectForwardRequest, easyssh.DirectPortForwardHandler())
easyssh.HandleRequestFunc(easyssh.RemoteForwardRequest, easyssh.TCPIPForwardRequest)
easyssh.ListenAndServe(":22", config, nil)
}
我不确定您是否了解 SSH 隧道在您的代码中的工作原理。
您需要与远程(服务器)建立 SSH 连接。 然后设置 SSH 隧道,以便使用 SSH 连接将本地 TCP:8080 端口转发到远程服务器 TCP:8080 端口。实际8080端口可以通过防火墙关闭。
您可以使用 SSH 从您的客户端连接到您的服务器吗?
您需要检查 localhost:8080 端口并且您需要确保您的服务器 8080 端口也被某些应用程序监听。
看看here一些例子和理论。
我在 easyssh 中发现了一个与远程端口转发相关的错误:
https://dev.justinjudd.org/justin/easyssh/src/master/tcpip.go#L107
ssh.DiscardRequests(reqs)
应该是运行分开的goroutine
,否则下一次数据传输将不会执行。