You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过HTTP代理建立SSH连接?(Golang实现求助)

通过HTTP代理建立SSH连接(Go语言实现)

你的伪代码思路方向正确,但忽略了HTTP代理的核心协议要求:必须先发送CONNECT请求让代理建立到SSH服务器的隧道,之后才能传输SSH流量。直接调用proxyConn.Dial无效,因为普通TCP连接不会自动处理HTTP代理的协议逻辑。

正确实现步骤

  • 与HTTP代理建立TCP连接
  • 向代理发送CONNECT请求,指定SSH服务器的地址
  • 校验代理返回的响应状态码(需为200 OK),确认隧道建立成功
  • 基于已建立的隧道连接,初始化SSH客户端

完整代码示例

import (
	"bufio"
	"fmt"
	"net"
	"net/http"
	"golang.org/x/crypto/ssh"
)

func main() {
	proxyURL := "proxy.example.com:8080" // 你的HTTP代理地址
	serverURL := "ssh.example.com:22"    // SSH服务器地址
	sshConfig := &ssh.ClientConfig{
		User: "your-username",
		Auth: []ssh.AuthMethod{
			ssh.Password("your-password"), // 或替换为密钥认证逻辑
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 生产环境请替换为安全的主机密钥校验逻辑
	}

	// 1. 连接到HTTP代理
	proxyConn, err := net.Dial("tcp", proxyURL)
	if err != nil {
		panic(fmt.Sprintf("连接代理失败: %v", err))
	}
	defer proxyConn.Close()

	// 2. 发送CONNECT请求建立隧道
	connectReq, err := http.NewRequest("CONNECT", serverURL, nil)
	if err != nil {
		panic(fmt.Sprintf("构造CONNECT请求失败: %v", err))
	}
	// 若代理需要基础认证,取消注释以下代码
	// connectReq.SetBasicAuth("proxy-username", "proxy-password")

	err = connectReq.Write(proxyConn)
	if err != nil {
		panic(fmt.Sprintf("发送CONNECT请求失败: %v", err))
	}

	// 3. 校验代理响应
	resp, err := http.ReadResponse(bufio.NewReader(proxyConn), connectReq)
	if err != nil {
		panic(fmt.Sprintf("读取代理响应失败: %v", err))
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		panic(fmt.Sprintf("代理拒绝连接,状态码: %d", resp.StatusCode))
	}

	// 4. 基于隧道连接建立SSH客户端
	sshConn, chans, reqs, err := ssh.NewClientConn(proxyConn, serverURL, sshConfig)
	if err != nil {
		panic(fmt.Sprintf("建立SSH连接失败: %v", err))
	}
	defer sshConn.Close()

	client := ssh.NewClient(sshConn, chans, reqs)
	defer client.Close()

	// 测试:执行远程命令
	session, err := client.NewSession()
	if err != nil {
		panic(fmt.Sprintf("创建SSH会话失败: %v", err))
	}
	defer session.Close()

	output, err := session.CombinedOutput("echo Hello from SSH over HTTP proxy")
	if err != nil {
		panic(fmt.Sprintf("执行命令失败: %v", err))
	}
	fmt.Println(string(output))
}

注意事项

  • 生产环境禁止使用ssh.InsecureIgnoreHostKey(),应替换为基于已知主机密钥的校验逻辑,防范中间人攻击
  • 若代理需要其他类型认证(如NTLM),需扩展CONNECT请求的头信息或使用对应库处理
  • 可将HTTP代理隧道逻辑封装为自定义net.Conn实现,提升代码复用性

内容的提问来源于stack exchange,提问作者Sachavent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:17:29