在Golang中通过Tor建立TCP连接

huangapple go评论85阅读模式
英文:

TCP connection over Tor in Golang

问题

在Go语言中,是否可以通过Tor网络建立TCP连接?我查了一下,但没有找到相关的提及。

如果不行,是否有类似于TCP的替代方案,比如WebSockets?

注意:目前我没有源代码可以提供,因为还没有任何代码。这只是事先的研究。

英文:

Is it possible to initiate a TCP connection over the tor network in go? I've looked around but haven't found a mention of it.

If not, is there something similar to TCP - like websockets - that can be used instead?

Note: There's no source code for me to post at the moment since there isn't any yet. This is simply research beforehand.

答案1

得分: 25

一个Tor节点在端口9050上充当SOCKS代理。Go语言对SOCKS5协议的支持位于golang.org/x/net/proxy包中:

import "golang.org/x/net/proxy"

为了通过Tor进行连接,首先需要创建一个通过本地SOCKS5代理的新Dialer

dialer, err := proxy.SOCKS5("tcp", "127.0.0.1:9050", nil, nil)
if err != nil {
    log.Fatal(err)
}

要使用这个dialer,只需调用dialer.Dial而不是net.Dial

conn, err := dialer.Dial("tcp", "stackoverflow.com:80")
if err != nil {
    log.Fatal(err)
}
defer conn.Close()
英文:

A tor node acts as a SOCKS proxy on port 9050. Go support for the SOCKS5 protocol lives in package golang.org/x/net/proxy:

<!-- language-all: golang -->

import &quot;golang.org/x/net/proxy&quot;

In order to make connections through tor, you first need to create a new Dialer that goes through the local SOCKS5 proxy:

dialer, err := proxy.SOCKS5(&quot;tcp&quot;, &quot;127.0.0.1:9050&quot;, nil, nil)
if err != nil {
    log.Fatal(err)
}

To use this dialer, you just call dialer.Dial instead of net.Dial:

conn, err := dialer.Dial(&quot;tcp&quot;, &quot;stackoverflow.com:80&quot;)
if err != nil {
    log.Fatal(err)
}
defer conn.Close()

答案2

得分: 1

有三种方法可以指示客户端使用代理:

  1. 设置HTTP_PROXY环境变量:
export HTTP_PROXY="http://ProxyIP:ProxyPort"

HTTP_PROXY环境变量将用作HTTP请求和HTTPS请求的代理URL,除非被HTTPS_PROXYNO_PROXY覆盖。

在使用_tor_的情况下,它应该是这样的(在本地主机上运行tor时):

export HTTP_PROXY="socks5://127.0.0.1:9050"
  1. 明确指示HTTP客户端使用代理。以下是在Golang中的示例:
proxy, _ := url.Parse("http://ProxyIP:ProxyPort") 
httpClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxy)}}
  1. Golang还提供了"net/http"包的默认传输选项。此设置指示整个程序(包括默认的HTTP客户端)使用代理:
proxy, _ := url.Parse("http://ProxyIP:ProxyPort") 
http.DefaultTransport = &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxy)}}

你可以在这里找到使用代理的go HTTP客户端的示例这里

此外,你可以阅读有关如何在Docker容器中运行_tor_代理,以及如何将其作为Kubernetes的出口网关的一部分运行的信息这里

英文:

There are three ways to instruct a client to use a proxy:

  1. Set the HTTP_PROXY environment variable:
export HTTP_PROXY=&quot;http://ProxyIP:ProxyPort&quot;

HTTP_PROXY environment variable will be used as the proxy URL for HTTP requests and HTTPS requests, unless overridden by HTTPS_PROXY or NO_PROXY

In tor use case it should look like this (when running tor on localhost):

export HTTP_PROXY=&quot;socks5://127.0.0.1:9050&quot;
  1. Explicitly instructing the HTTP client to use a proxy. Here’s an example in Golang:
proxy, _ := url.Parse(&quot;http://ProxyIP:ProxyPort&quot;) 
httpClient := &amp;http.Client{Transport: &amp;http.Transport{Proxy: http.ProxyURL(proxy)}}
  1. Golang also offers the default transport option as part of the &quot;net/http&quot; package. This setting instructs the entire program (including the default HTTP client) to use the proxy:
proxy, _ := url.Parse(&quot;http://ProxyIP:ProxyPort&quot;) 
http.DefaultTransport = &amp;http.Client{Transport: &amp;http.Transport{Proxy: http.ProxyURL(proxy)}}

You can find example of go HTTP client using proxy here.

Also, you can read about how to run tor proxy inside a Docker container, how to run it as part of Kubernetes as an egress gateway here.

答案3

得分: 1

最便携的方法是使用由Chad Retz编写的包装器。

它将所需的 Tor 资源嵌入到您的二进制文件中,这样您就可以分发它并确保您的应用程序通过 Tor 运行。

在这种情况下,最终用户不需要安装 TBB 或其他任何东西,只需安装您的应用程序即可。

不过,老实说,它不包括 Tor 引擎的自动更新,所以您需要在您的端上执行一些操作以确保最高的安全性。

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/cretz/bine/tor"
)

func main() {
	// 使用默认配置启动 Tor(可以将 start conf 的 DebugWriter 设置为 os.Stdout 以获取调试日志)
	fmt.Println("正在启动并注册 Onion 服务,请稍等几分钟...")
	t, err := tor.Start(nil, nil)
	if err != nil {
		log.Panicf("无法启动 Tor:%v", err)
	}
	defer t.Close()
	// 等待最多几分钟来发布服务
	listenCtx, listenCancel := context.WithTimeout(context.Background(), 3*time.Minute)
	defer listenCancel()
	// 创建一个 v3 Onion 服务,监听任意端口但显示为 80
	onion, err := t.Listen(listenCtx, &tor.ListenConf{Version3: true, RemotePorts: []int{80}})
	if err != nil {
		log.Panicf("无法创建 Onion 服务:%v", err)
	}
	defer onion.Close()
	fmt.Printf("打开 Tor 浏览器并导航到 http://%v.onion\n", onion.ID)
	fmt.Println("按回车键退出")
	// 从 HTTP 服务器提供当前文件夹
	errCh := make(chan error, 1)
	go func() { errCh <- http.Serve(onion, http.FileServer(http.Dir("."))) }()
	// 当按下回车键时结束
	go func() {
		fmt.Scanln()
		errCh <- nil
	}()
	if err = <-errCh; err != nil {
		log.Panicf("服务提供失败:%v", err)
	}
}
英文:

the most portable way to achieve this is to use the wrapper wrote by Chad Retz

It will embed tor required assets into your binary. So that you can distribute it and ensure your app goes through tor.

In that scenario the end user does not need to install TBB or anything else other than your app.

Though to be honest, it does not include automatic updates of the tor engine, so this is something to perform on your end to ensure top security.

package main

import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;time&quot;

	&quot;github.com/cretz/bine/tor&quot;
)

func main() {
	// Start tor with default config (can set start conf&#39;s DebugWriter to os.Stdout for debug logs)
	fmt.Println(&quot;Starting and registering onion service, please wait a couple of minutes...&quot;)
	t, err := tor.Start(nil, nil)
	if err != nil {
		log.Panicf(&quot;Unable to start Tor: %v&quot;, err)
	}
	defer t.Close()
	// Wait at most a few minutes to publish the service
	listenCtx, listenCancel := context.WithTimeout(context.Background(), 3*time.Minute)
	defer listenCancel()
	// Create a v3 onion service to listen on any port but show as 80
	onion, err := t.Listen(listenCtx, &amp;tor.ListenConf{Version3: true, RemotePorts: []int{80}})
	if err != nil {
		log.Panicf(&quot;Unable to create onion service: %v&quot;, err)
	}
	defer onion.Close()
	fmt.Printf(&quot;Open Tor browser and navigate to http://%v.onion\n&quot;, onion.ID)
	fmt.Println(&quot;Press enter to exit&quot;)
	// Serve the current folder from HTTP
	errCh := make(chan error, 1)
	go func() { errCh &lt;- http.Serve(onion, http.FileServer(http.Dir(&quot;.&quot;))) }()
	// End when enter is pressed
	go func() {
		fmt.Scanln()
		errCh &lt;- nil
	}()
	if err = &lt;-errCh; err != nil {
		log.Panicf(&quot;Failed serving: %v&quot;, err)
	}
}

huangapple
  • 本文由 发表于 2016年10月30日 18:19:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/40328025.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定