如何通过 TOR 路由 TCP 连接?

如何通过 TOR 路由 TCP 连接?

我正在读托尔查特它本质上是一个匿名聊天程序。

这听起来很酷,所以我想尝试自己做一个。首先,我编写了一个测试来使用 Http 抓取网页。由于 .NET 不支持 SOCKS4A/SOCKS5,我使用了 privoxy,我的应用程序运行正常。然后我切换到 TCP 回显测试,但 privoxy 不支持 TCP,因此我搜索并安装了 6 个以上的代理应用程序(freecap、socat、freeproxy、delegate 是我能记住的,我还玩过 putty,因为我知道它支持隧道和 SOCK5),但我无法成功让它们中的任何一个工作,更不用说让它通过我的 http 测试运行了,而 privoxy 可以轻松而轻松地做到了这一点。

我可以使用什么来让 TCP 连接通过 TOR?我花了 2 个多小时却没有成功。我不知道我是否在寻找中继、隧道、转发器、代理或代理链,而这些都出现在我的搜索中。我使用下面的 .NET 配置。我需要 TCP 工作,但我首先使用 http 进行测试,因为我知道我使用 privoxy 就可以让它工作。我使用哪些应用程序和配置来让 TCP 通过 tor?

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.net>
    <defaultProxy enabled="true">
      <proxy bypassonlocal="True" proxyaddress="http://127.0.0.1:8118"/>
    </defaultProxy>
    <settings>
      <httpWebRequest useUnsafeHeaderParsing="true"/>
    </settings>
  </system.net>
</configuration>

-编辑- 感谢 Bernd,我找到了解决方案。这是我最终编写的代码。虽然不惊人,但很公平。

static NetworkStream ConnectSocksProxy(string proxyDomain, short proxyPort, string host, short hostPort, TcpClient tc)
{
    tc.Connect(proxyDomain, proxyPort);
    if (System.Text.RegularExpressions.Regex.IsMatch(host, @"[\:/\\]"))
        throw new Exception("Invalid Host name. Use FQDN such as www.google.com. Do not have http, a port or / in it");
    NetworkStream ns = tc.GetStream();
    var HostNameBuf = new ASCIIEncoding().GetBytes(host);
    var HostPortBuf = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(hostPort));
    if (true) //5
    {
        var bufout = new byte[128];
        var buflen = 0;
        ns.Write(new byte[] { 5, 1, 0 }, 0, 3);
        buflen = ns.Read(bufout, 0, bufout.Length);
        if (buflen != 2 || bufout[0] != 5 || bufout[1] != 0)
            throw new Exception();

        var buf = new byte[] { 5, 1, 0, 3, (byte)HostNameBuf.Length };
        var mem = new MemoryStream();
        mem.Write(buf, 0, buf.Length);
        mem.Write(HostNameBuf, 0, HostNameBuf.Length);
        mem.Write(new byte[] { HostPortBuf[0], HostPortBuf[1] }, 0, 2);
        var memarr = mem.ToArray();
        ns.Write(memarr, 0, memarr.Length);
        buflen = ns.Read(bufout, 0, bufout.Length);
        if (bufout[0] != 5 || bufout[1] != 0)
            throw new Exception();
    }
    else //4a
    {
        var bufout = new byte[128];
        var buflen = 0;
        var mem = new MemoryStream();
        mem.WriteByte(4);
        mem.WriteByte(1);
        mem.Write(HostPortBuf, 0, 2);
        mem.Write(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(1)), 0, 4);
        mem.WriteByte(0);
        mem.Write(HostNameBuf, 0, HostNameBuf.Length);
        mem.WriteByte(0);
        var memarr = mem.ToArray();
        ns.Write(memarr, 0, memarr.Length);
        buflen = ns.Read(bufout, 0, bufout.Length);
        if (buflen != 8 || bufout[0] != 0 || bufout[1] != 90)
            throw new Exception();
    }
    return ns;
}

用法

using (TcpClient client = new TcpClient())
using (var ns = ConnectSocksProxy("127.0.0.1", 9050, "website.com", 80, client)) {...}

答案1

Socks4a 非常简单。你可以用 5 行代码手动实现 socks4a。查看 socks RFC(或维基百科上更简单的解释)。

本质上,您只需与 socks 代理建立正常的 TCP 连接(这意味着,在 tor 的情况下,您只需连接到 127.0.0.1 端口 9050,连接就会被接受,然后您通过此连接发送一个非常简单的请求(示例在 RFC 中给出),然后过一段时间,tor 将用 8 个字节答复(第二个字节是状态,应该是 90,表示成功)。就这样。

在此连接上收到 Tor 的成功答复后,您继续使用相同的连接,此时您已经通过此套接字与另一端建立连接,从此刻起,它的行为就像任何其他 TCP 连接一样,您可以像直接连接一样开始发送/接收。

编辑:您不需要研究整个 RFC,维基百科中对 Socks 4a 有一个非常简短而完整的描述(socks 5 对您的需求来说有点过度,而且 socks 4 无法解析主机名,因此 4a 是 Tor 的理想选择):

这里是 http://en.wikipedia.org/wiki/SOCKS#SOCKS4a

相关内容