Go の HTTP クライアントにおける SOCKS5 のホスト名解決
Go の標準 HTTP transport で socks5 と socks5h が異なる DNS モードを選ばない理由を説明します。
Go 1.27.3 の標準 HTTP transport では、socks5 と socks5h は接続先名を同じ方法で扱います。ホスト名の接続先は、ホスト名のままプロキシに送られます。スキームを切り替えても、curl のようにローカル DNS とリモート 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 リレーもテストしません。