Go HTTP 客户端中的 SOCKS5 主机名解析
了解为什么 socks5 与 socks5h 在 Go 标准 HTTP transport 中并不选择不同的 DNS 模式。
在 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 中继。