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 リレーもテストしません。

関連記事