Golang使用Tor SOCKS5代理报错connection reset by peer求助
问题排查与解决方案
先别急,咱们一步步来拆解这个connection reset by peer错误,核心原因大概率是容器内的Tor默认配置限制了外部连接,再加上Tor启动需要初始化时间,才导致你的Go程序请求被拒绝。
1. 修正Tor容器的核心配置
默认的Tor只会监听容器内部的回环地址(127.0.0.1),并且只允许容器本地发起SOCKS连接,宿主机通过端口映射过来的请求会直接被拒绝。我们需要修改配置放开限制:
更新Dockerfile
在你的Dockerfile中添加自定义Tor配置:
FROM alpine:edge RUN apk update && apk add tor # 让Tor监听容器所有网卡接口,并允许任意IP的SOCKS连接 RUN echo -e "SocksPort 0.0.0.0:9050\nSocksPolicy accept 0.0.0.0/0" > /etc/tor/torrc EXPOSE 9050 USER tor CMD ["/usr/bin/tor"]
重新构建并启动容器
# 先删除旧容器(如果存在) docker rm -f tor # 构建新镜像 docker build -t tor-custom . # 启动容器 docker run --name tor -p 11000:9050 tor-custom
2. 等待Tor完全启动
Tor启动时需要生成加密密钥并完成网络引导,这个过程大概需要30-60秒。你可以通过容器日志确认启动状态:
docker logs tor
当看到日志里出现Bootstrapped 100% (done): Done时,再运行你的Go程序,避免过早发起请求导致连接失败。
3. 修正Go代码的细节问题
第一种代码(访问普通HTTP网站)
你的代码逻辑没问题,但建议延长超时时间(Tor网络速度较慢),并使用更稳定的测试URL:
package main import ( "fmt" "net/http" "net/url" "time" ) func main() { proxyUrl, err := url.Parse("socks5://127.0.0.1:11000") if err != nil { panic(err) } cl := http.Client{ Transport: &http.Transport{ Proxy: http.ProxyURL(proxyUrl), }, Timeout: 30 * time.Second, // 延长超时适配Tor网络 } resp, err := cl.Get("http://example.com/") if err != nil { panic(err) } defer resp.Body.Close() fmt.Println("Response Status:", resp.Status) }
第二种代码(访问.onion网站)
你的代码缺失了部分依赖包导入,修正后的完整版本:
package main import ( "context" "fmt" "io/ioutil" "net" "net/http" "os" "golang.org/x/net/proxy" ) const ( PROXY_ADDR = "127.0.0.1:11000" URL = "http://facebookcorewwwi.onion" ) func main() { // 创建socks5拨号器 dialer, err := proxy.SOCKS5("tcp", PROXY_ADDR, nil, proxy.Direct) if err != nil { fmt.Fprintln(os.Stderr, "can't connect to the proxy:", err) os.Exit(1) } dialContext := func(ctx context.Context, network, address string) (net.Conn, error) { return dialer.Dial(network, address) } // 设置HTTP客户端 httpTransport := &http.Transport{ DialContext: dialContext, } httpClient := &http.Client{ Transport: httpTransport, Timeout: 30 * time.Second, // 延长超时 } // 创建请求 req, err := http.NewRequest("GET", URL, nil) if err != nil { fmt.Fprintln(os.Stderr, "can't create request:", err) os.Exit(2) } resp, err := httpClient.Do(req) if err != nil { fmt.Fprintln(os.Stderr, "cannot make get request: ", err) os.Exit(2) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Fprintln(os.Stderr, "cannot read response body: ", err) os.Exit(2) } fmt.Println("received response length:", len(body)) fmt.Println("response preview:", string(body[:100])) // 只打印前100个字符避免输出过长 }
额外验证步骤
如果还是有问题,先用curl测试代理是否正常:
curl -x socks5://127.0.0.1:11000 http://example.com/
如果curl能正常返回内容,说明代理没问题,再检查Go代码的细节即可。
内容的提问来源于stack exchange,提问作者aquaman
相关产品推荐
相关产品推荐

