在 Go 1.27.3 的标准 HTTP transport 中,socks5 和 socks5h 对目标名称的处理相同。主机名目标会以主机名形式发送给代理。切换这两个方案,并不会像 curl 那样在本地与远程 DNS 之间切换。

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/url"
    "time"
)

func main() {
    proxyURL, err := url.Parse("socks5://203.0.113.10:1080")
    if err != nil {
        log.Fatal(err)
    }

    transport := http.DefaultTransport.(*http.Transport).Clone()
    transport.Proxy = http.ProxyURL(proxyURL)
    defer transport.CloseIdleConnections()

    client := &http.Client{
        Transport: transport,
        Timeout: 15 * time.Second,
    }
    response, err := client.Get("https://example.com/")
    if err != nil {
        log.Fatal(err)
    }
    defer response.Body.Close()
    fmt.Println(response.StatusCode)
}

将文档示例地址替换为你的 SOCKS5 端点;可在 SOCKS5 代理列表浏览候选。示例使用 net/http 自身的 transport;其他 Go 库可能实现不同的行为。

仍需区分两个名称。数字形式的代理地址不需要查询代理主机名;使用名称的代理则必须先在本地找到,才能发送 SOCKS 请求。数字形式的目标没有待解析的目标名称,无法用来展示主机名处理方式。要检查实际的 SOCKS 选择,应查看目标字段携带的是名称还是地址。

标准 transport 支持 http、https、socks5 和 socks5h 代理方案。泛称 SOCKS 的标签并不能证明端点支持 SOCKS5。示例通过 TCP 发送 HTTP,既未测试其他 SOCKS 命令,也未测试 UDP 中继。

相关文章