quic-go不支持HTTP/2式请求代理,如何配置HTTP/S或SOCKS5代理?
为quic-go的HTTP/3请求配置HTTP/S或SOCKS5代理
quic-go本身的HTTP/3客户端没有内置代理支持,需要手动通过代理隧道+QUIC会话绑定的方式实现,以下分两种代理类型给出具体方案:
HTTP/S代理实现
HTTP/S代理通过CONNECT方法建立TCP隧道,我们需要先完成隧道建立,再在这个TCP连接上创建QUIC会话:
步骤与代码示例
package main import ( "bufio" "context" "crypto/tls" "fmt" "net" "net/http" "net/url" "github.com/quic-go/quic-go" "github.com/quic-go/quic-go/http3" ) func main() { // 配置代理与目标地址 proxyAddr := "http://your-proxy:8080" targetURL, _ := url.Parse("https://example.com") // 建立到代理的TCP连接 proxyURL, _ := url.Parse(proxyAddr) proxyConn, err := net.Dial("tcp", proxyURL.Host) if err != nil { panic(err) } defer proxyConn.Close() // 发送CONNECT请求创建隧道 connectReq := &http.Request{ Method: "CONNECT", URL: &url.URL{Host: targetURL.Host}, Host: targetURL.Host, } // 若代理需要认证,添加Authorization头 // connectReq.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte("user:pass"))) if err := connectReq.Write(proxyConn); err != nil { panic(err) } // 验证代理响应 resp, err := http.ReadResponse(bufio.NewReader(proxyConn), connectReq) if err != nil { panic(err) } if resp.StatusCode != http.StatusOK { panic(fmt.Sprintf("proxy rejected: %s", resp.Status)) } // 配置TLS与QUIC会话 tlsCfg := &tls.Config{ ServerName: targetURL.Hostname(), NextProtos: []string{"h3"}, // 指定HTTP/3的ALPN协议 } quicConn, err := quic.DialEarlyContext(context.Background(), proxyConn, targetURL.Host, tlsCfg, nil) if err != nil { panic(err) } defer quicConn.CloseWithError(0, "") // 绑定QUIC会话到HTTP/3客户端 client := &http3.Client{ RoundTripper: &http3.RoundTripper{ Dial: func(ctx context.Context, addr string, t *tls.Config, c *quic.Config) (quic.EarlyConnection, error) { return quicConn, nil }, }, } // 发起HTTP/3请求 req, _ := http.NewRequest(http.MethodGet, targetURL.String(), nil) resp, err = client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() fmt.Println("Response Status:", resp.Status) }
SOCKS5代理实现
SOCKS5代理需要先完成握手建立隧道,推荐使用golang.org/x/net/proxy包简化握手逻辑:
步骤与代码示例
package main import ( "context" "crypto/tls" "fmt" "net/http" "net/url" "github.com/quic-go/quic-go" "github.com/quic-go/quic-go/http3" "golang.org/x/net/proxy" ) func main() { // 配置SOCKS5代理与目标地址 socks5Addr := "socks5://your-proxy:1080" targetURL, _ := url.Parse("https://example.com") // 创建SOCKS5拨号器 proxyURL, _ := url.Parse(socks5Addr) // 若代理需要认证,添加Auth参数 // auth := proxy.Auth{User: "username", Password: "password"} // dialer, err := proxy.SOCKS5("tcp", proxyURL.Host, &auth, proxy.Direct) dialer, err := proxy.FromURL(proxyURL, proxy.Direct) if err != nil { panic(err) } // 通过SOCKS5代理建立到目标的TCP连接 proxyConn, err := dialer.Dial("tcp", targetURL.Host) if err != nil { panic(err) } defer proxyConn.Close() // 配置TLS与QUIC会话 tlsCfg := &tls.Config{ ServerName: targetURL.Hostname(), NextProtos: []string{"h3"}, } quicConn, err := quic.DialEarlyContext(context.Background(), proxyConn, targetURL.Host, tlsCfg, nil) if err != nil { panic(err) } defer quicConn.CloseWithError(0, "") // 绑定会话到HTTP/3客户端 client := &http3.Client{ RoundTripper: &http3.RoundTripper{ Dial: func(ctx context.Context, addr string, t *tls.Config, c *quic.Config) (quic.EarlyConnection, error) { return quicConn, nil }, }, } // 发起请求 req, _ := http.NewRequest(http.MethodGet, targetURL.String(), nil) resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() fmt.Println("Response Status:", resp.Status) }
注意事项
- 依赖安装:执行
go get github.com/quic-go/quic-go和go get golang.org/x/net/proxy获取所需包。 - 代理认证:HTTP/S代理通过添加
Authorization头实现,SOCKS5代理通过proxy.Auth结构体配置。 - UDP代理说明:上述方案基于TCP隧道传输QUIC数据,若需直接使用UDP的SOCKS5代理,需实现SOCKS5的UDP关联逻辑,复杂度较高,上述方法为通用兼容方案。
内容的提问来源于stack exchange,提问作者Võ Bảo
相关产品推荐
相关产品推荐

