英文:
How to connect remote ssh server with socks proxy?
问题
以下是代码的翻译:
package main
import (
"errors"
"fmt"
"net"
"golang.org/x/crypto/ssh"
)
var (
socks string = "127.0.0.1:8000"
server string = "192.168.1.1:2222"
cmd string = ""
login string = "root"
password string = ""
)
func main() {
c, err := netConn(socks)
if err != nil {
fmt.Println(err)
}
conf := &ssh.ClientConfig{
User: login,
Auth: []ssh.AuthMethod{
ssh.Password(password),
},
}
client, err := Dialer(conf, c, server)
if err != nil {
fmt.Println(err)
}
session, err := client.NewSession()
defer session.Close()
if err != nil {
fmt.Println(err)
}
session.Run(cmd)
}
func netConn(addr string) (net.Conn, error) {
conn, err := net.Dial("tcp", addr)
if err != nil {
return nil, errors.New(fmt.Sprintf("无法连接到 %v", err))
}
return conn, nil
}
func Dialer(conf *ssh.ClientConfig, c net.Conn, host string) (*ssh.Client, error) {
conn, chans, reqs, err := ssh.NewClientConn(c, host, conf)
if err != nil {
return nil, err
}
return ssh.NewClient(conn, chans, reqs), nil
}
客户端报错
ssh: 握手失败: EOF
panic: 运行时错误: 无效的内存地址或空指针解引用
[signal 0xb code=0x1 addr=0x0 pc=0x80f3e2d]
goroutine 1 [running]:
panic(0x8201b60, 0x18522030)
/usr/lib/go/src/runtime/panic.go:464 +0x326
golang.org/x/crypto/ssh.(*Client).NewSession(0x0, 0x1, 0x0, 0x0)
/home/user/go/src/golang.org/x/crypto/ssh/client.go:129 +0xcd
main.main()
/home/user/go/src/ss/i.go:34 +0x276
并且在日志中看到 socks 服务器报错
[ERR] socks: 不支持的 SOCKS 版本: [83]
我该如何解决这个问题?谢谢。
英文:
package main
import (
"errors"
"fmt"
"net"
"golang.org/x/crypto/ssh"
)
var (
socks string = "127.0.0.1:8000"
server string = "192.168.1.1:2222"
cmd string = ""
login string = "root"
password string = ""
)
func main() {
c, err := netConn(socks)
if err != nil {
fmt.Println(err)
}
conf := &ssh.ClientConfig{
User: login,
Auth: []ssh.AuthMethod{
ssh.Password(password),
},
}
client, err := Dialer(conf, c, server)
if err != nil {
fmt.Println(err)
}
session, err := client.NewSession()
defer session.Close()
if err != nil {
fmt.Println(err)
}
session.Run(cmd)
}
func netConn(addr string) (net.Conn, error) {
conn, err := net.Dial("tcp", addr)
if err != nil {
return nil, errors.New(fmt.Sprintf("Unable to connect to %v", err))
}
return conn, nil
}
func Dialer(conf *ssh.ClientConfig, c net.Conn, host string) (*ssh.Client, error) {
conn, chans, reqs, err := ssh.NewClientConn(c, host, conf)
if err != nil {
return nil, err
}
return ssh.NewClient(conn, chans, reqs), nil
}
Client panic
> ssh: handshake failed: EOF
>
>panic: runtime error: invalid memory address or nil pointer dereference
>
>[signal 0xb code=0x1 addr=0x0 pc=0x80f3e2d]
>
>goroutine 1 [running]:
>
>panic(0x8201b60, 0x18522030)
>
> /usr/lib/go/src/runtime/panic.go:464 +0x326
>
>golang.org/x/crypto/ssh.(*Client).NewSession(0x0, 0x1, 0x0, 0x0)
>
> /home/user/go/src/golang.org/x/crypto/ssh/client.go:129 +0xcd
>
>main.main()
>
> /home/user/go/src/ss/i.go:34 +0x276
And socks server in log
>[ERR] socks: Unsupported SOCKS version: [83]
How i can make it posible? Thanks.
答案1
得分: 7
你可以按照以下方式使用x/net/proxy
包:
package main
import (
"log"
"golang.org/x/crypto/ssh"
"golang.org/x/net/proxy"
)
func main() {
sshConfig := &ssh.ClientConfig{
User: "user",
// Auth: .... fill out with keys etc as normal
}
client, err := proxiedSSHClient("127.0.0.1:8000", "127.0.0.1:22", sshConfig)
if err != nil {
log.Fatal(err)
}
// 获取一个会话等...
}
func proxiedSSHClient(proxyAddress, sshServerAddress string, sshConfig *ssh.ClientConfig) (*ssh.Client, error) {
dialer, err := proxy.SOCKS5("tcp", proxyAddress, nil, proxy.Direct)
if err != nil {
return nil, err
}
conn, err := dialer.Dial("tcp", sshServerAddress)
if err != nil {
return nil, err
}
c, chans, reqs, err := ssh.NewClientConn(conn, sshServerAddress, sshConfig)
if err != nil {
return nil, err
}
return ssh.NewClient(c, chans, reqs), nil
}
希望对你有帮助!
英文:
You can use the x/net/proxy
package as follows:
package main
import (
"log"
"golang.org/x/crypto/ssh"
"golang.org/x/net/proxy"
)
func main() {
sshConfig := &ssh.ClientConfig{
User: "user",
// Auth: .... fill out with keys etc as normal
}
client, err := proxiedSSHClient("127.0.0.1:8000", "127.0.0.1:22", sshConfig)
if err != nil {
log.Fatal(err)
}
// get a session etc...
}
func proxiedSSHClient(proxyAddress, sshServerAddress string, sshConfig *ssh.ClientConfig) (*ssh.Client, error) {
dialer, err := proxy.SOCKS5("tcp", proxyAddress, nil, proxy.Direct)
if err != nil {
return nil, err
}
conn, err := dialer.Dial("tcp", sshServerAddress)
if err != nil {
return nil, err
}
c, chans, reqs, err := ssh.NewClientConn(conn, sshServerAddress, sshConfig)
if err != nil {
return nil, err
}
return ssh.NewClient(c, chans, reqs), nil
}
答案2
得分: 0
根据ssh包的API,可以看到Dial函数的返回类型是ssh.Client的对象。因此,你可以使用以下代码来简化你的代码:
func main() {
conf := &ssh.ClientConfig{
User: login,
Auth: []ssh.AuthMethod{
ssh.Password(password),
},
}
client, err := ssh.Dial("tcp", server, conf)
if err != nil {
fmt.Println(err)
}
defer client.Close()
session, err := client.NewSession()
defer session.Close()
if err != nil {
fmt.Println(err)
}
session.Run(cmd)
}
希望对你有帮助!
英文:
As you can see from the ssh package API, the function
func Dial(network, addr string, config *ClientConfig) (*Client, error)
directly returns an object of type ssh.Client.
Therefore you can shorten a lot your code with:
func main() {
conf := &ssh.ClientConfig{
User: login,
Auth: []ssh.AuthMethod{
ssh.Password(password),
},
}
client, err := ssh.Dial("tcp", server, conf)
if err != nil {
fmt.Println(err)
}
defer client.Close()
session, err := client.NewSession()
defer session.Close()
if err != nil {
fmt.Println(err)
}
session.Run(cmd)
}
Hope this helps !
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论