我正在读托尔查特它本质上是一个匿名聊天程序。
这听起来很酷,所以我想尝试自己做一个。首先,我编写了一个测试来使用 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 的理想选择):