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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:09:45