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

求助:基于现有net.Conn的Go代理服务器实现及HTTP请求方案

基于Snowflake net.Conn的Go代理实现与直接HTTP请求方案

一、用现有net.Conn实现HTTP代理转发

你可以实现一个简单的HTTP代理服务器,将本地客户端的HTTP请求通过Snowflake建立的net.Conn转发出去,再把远端响应回传给本地客户端。核心逻辑是双向数据拷贝:将客户端连接的数据拷贝到Snowflake conn,同时将Snowflake conn的数据拷贝回客户端连接。

以下是结合你的Snowflake代码的完整实现:

package main

import (
    "io"
    "log"
    "net"
    "net/http"

    sf "git.torproject.org/pluggable-transports/snowflake.git/v2/client/lib"
)

// 代理处理器:将HTTP请求转发到Snowflake连接
func proxyHandler(snowflakeConn net.Conn) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // 修改请求目标:代理场景下需将请求URL设为完整地址
        r.RequestURI = ""
        r.URL.Scheme = "http" // 若需HTTPS,需在Snowflake conn之上建立TLS连接
        r.URL.Host = "目标服务器地址:端口" // 替换为实际要访问的服务地址

        // 将HTTP请求写入Snowflake连接
        if err := r.Write(snowflakeConn); err != nil {
            log.Printf("写入Snowflake连接失败: %v", err)
            w.WriteHeader(http.StatusServiceUnavailable)
            return
        }

        // 读取Snowflake连接返回的响应,回传给客户端
        _, err := io.Copy(w, snowflakeConn)
        if err != nil {
            log.Printf("响应回传客户端失败: %v", err)
        }
    }
}

func main() {
    // 初始化Snowflake客户端(原有代码)
    config := sf.ClientConfig{
        BrokerURL:   "https://snowflake-broker.torproject.net.global.prod.fastly.net/",
        FrontDomain: "cdn.sstatic.net",
        ICEAddresses: []string{
            "stun:stun.voip.blackberry.com:3478",
            "stun:stun.stunprotocol.org:3478",
            "stun:stun.altar.com.pl:3478",
            "stun:stun.antisip.com:3478",
            "stun:stun.bluesip.net:3478",
            "stun:stun.dus.net:3478",
            "stun:stun.epygi.com:3478",
            "stun:stun.sonetel.com:3478",
            "stun:stun.sonetel.net:3478",
            "stun:stun.uls.co.za:3478",
            "stun:stun.voipgate.com:3478",
            "stun:stun.voys.nl:3478"},
        Max: 1,
    }
    transport, err := sf.NewSnowflakeClient(config)
    if err != nil {
        log.Fatal("启动Snowflake传输失败: ", err)
    }

    // 建立Snowflake连接
    conn, err := transport.Dial()
    if err != nil {
        log.Printf("连接失败: %s", err)
        return
    }
    defer conn.Close()

    // 启动本地HTTP代理,监听8080端口
    log.Println("HTTP代理已启动,监听端口:8080")
    http.HandleFunc("/", proxyHandler(conn))
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal("代理服务器启动失败: ", err)
    }
}

注意事项

  • 若需支持HTTPS代理,需在Snowflake conn之上包装TLS客户端:tlsClient := tls.Client(conn, &tls.Config{ServerName: "目标域名"}),之后使用tlsClient进行读写。
  • 若要实现SOCKS5代理,逻辑类似,只需替换协议解析部分,核心仍是双向数据拷贝。

二、直接通过net.Conn发送HTTP请求(不使用http.Client)

如果不需要代理服务器,仅需直接通过Snowflake连接发送HTTP请求,可以手动构造符合HTTP协议格式的报文,写入net.Conn后读取响应。

示例代码如下:

package main

import (
    "bufio"
    "log"
    "net"
    "strings"

    sf "git.torproject.org/pluggable-transports/snowflake.git/v2/client/lib"
)

func main() {
    // 初始化Snowflake客户端(原有代码)
    config := sf.ClientConfig{
        BrokerURL:   "https://snowflake-broker.torproject.net.global.prod.fastly.net/",
        FrontDomain: "cdn.sstatic.net",
        ICEAddresses: []string{
            "stun:stun.voip.blackberry.com:3478",
            "stun:stun.stunprotocol.org:3478",
            "stun:stun.altar.com.pl:3478",
            "stun:stun.antisip.com:3478",
            "stun:stun.bluesip.net:3478",
            "stun:stun.dus.net:3478",
            "stun:stun.epygi.com:3478",
            "stun:stun.sonetel.com:3478",
            "stun:stun.sonetel.net:3478",
            "stun:stun.uls.co.za:3478",
            "stun:stun.voipgate.com:3478",
            "stun:stun.voys.nl:3478"},
        Max: 1,
    }
    transport, err := sf.NewSnowflakeClient(config)
    if err != nil {
        log.Fatal("启动Snowflake传输失败: ", err)
    }

    // 建立Snowflake连接
    conn, err := transport.Dial()
    if err != nil {
        log.Printf("连接失败: %s", err)
        return
    }
    defer conn.Close()

    // 手动构造HTTP GET请求报文(严格遵循HTTP协议格式)
    request := "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n"
    // 写入Snowflake连接
    _, err = conn.Write([]byte(request))
    if err != nil {
        log.Fatal("写入请求失败: ", err)
    }

    // 读取并打印响应
    scanner := bufio.NewScanner(conn)
    for scanner.Scan() {
        log.Println(scanner.Text())
    }
    if err := scanner.Err(); err != nil {
        log.Fatal("读取响应失败: ", err)
    }
}

说明

  • 手动构造HTTP请求时,必须严格遵守协议规范:行尾使用\r\n,请求头结束后需添加空行(\r\n\r\n)。
  • 发送POST请求时,需额外添加Content-Length头,并在空行后写入请求体内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 14:25:13