把 SOCKS 打开的连接交给 Go 的 SSH 客户端
用 x/net/proxy 拨号到 SSH 目标,再在得到的 net.Conn 上初始化 x/crypto/ssh。
SOCKS 拨号器提供传输层,SSH 包在其上完成 SSH 握手。事后再调用 ssh.Dial 会另建一条连接,而不会复用这个传输层。
在已经使用 x/net/proxy 和 x/crypto/ssh 的应用里,辅助函数可以直接返回配置好的 SSH 客户端:
func dialSSHViaSOCKS(proxyAddr, sshAddr string,
config *ssh.ClientConfig) (*ssh.Client, error) {
dialer, err := proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
if err != nil {
return nil, err
}
conn, err := dialer.Dial("tcp", sshAddr)
if err != nil {
return nil, err
}
transport, channels, requests, err :=
ssh.NewClientConn(conn, sshAddr, config)
if err != nil {
conn.Close()
return nil, err
}
return ssh.NewClient(transport, channels, requests), nil
}这里的包名是 golang.org/x/net/proxy 和 golang.org/x/crypto/ssh。proxyAddr 指定 SOCKS 监听地址;sshAddr 以 host:port 指定最终服务器。
在 config 中提供应用惯用的 SSH 用户、认证方式和 HostKeyCallback。knownhosts 包可以用可信的 known_hosts 文件构建该回调。把目标主机名传给 NewClientConn,主机密钥比对才会使用预期的 SSH 身份。
nil 参数表示不使用 SOCKS 凭据。对于允许访问的公共 SSH 目标,SOCKS5 代理列表中无需账号的条目可以提供 proxyAddr,前提是它放行实际的 SSH 主机和端口。需要时传入带代理账号的 proxy.Auth;SSH 认证仍然留在 config 里。
NewClient 接收 NewClientConn 返回的入站通道与请求流,并接管这些客户端机制。工作结束后关闭返回的 SSH 客户端。生产环境的连接处理还需要限时拨号与握手策略;这个辅助函数只演示传输层的交接。