Назад | Перейти на главную страницу

Как маршрутизировать TCP-соединения через TOR?

Я читал о торчат который по сути является программой анонимного чата.

Это звучало круто, поэтому я хотел поэкспериментировать и сделать свой собственный. Сначала я написал тест для захвата веб-страницы с помощью Http. Sicne .NET не поддерживает SOCKS4A / SOCKS5, я использовал Privoxy, и мое приложение работало. Затем я переключаюсь на эхо-тест TCP, и Privoxy не поддерживает TCP, поэтому я поискал и установил 6+ прокси-приложений (freecap, socat, freeproxy, delegate - это те, которые я могу вспомнить с макушки, я также играл с putty bc i знаю, что он поддерживает туннели и 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>

-edit- Благодаря Бернду у меня есть решение. Вот код, который я написал. Это не удивительно, но справедливо.

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)) {...}

Socks4a действительно прост. Вы можете выполнить socks4a вручную в 5 строках кода. Взгляните на socks RFC (или его более простое объяснение в Википедии).

По сути, вы просто выполняете обычное TCP-соединение с прокси-сервером socks (это означает, что в случае, если вы просто подключаетесь к порту 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