Как использовать протокол управления Tor в C #? - PullRequest
14 голосов
/ 30 апреля 2010

Я пытаюсь программно отправить команды на порт управления Tor, чтобы он обновил цепочку. Я не смог найти никаких примеров в C #, и мое решение не работает. Время ожидания запроса истекло. У меня запущена служба, и я вижу, что она прослушивает порт управления.

public string Refresh()
{
    TcpClient client = new TcpClient("localhost", 9051);
    string response = string.Empty;
    string authenticate = MakeTcpRequest("AUTHENTICATE\r\n", client);
    if (authenticate.Equals("250"))
    {
        response = MakeTcpRequest("SIGNAL NEWNYM\r\n", client);
    }
    client.Close();
    return response;
}

public string MakeTcpRequest(string message, TcpClient client)
{
    client.ReceiveTimeout = 20000;
    client.SendTimeout = 20000;
    string proxyResponse = string.Empty;

    try
    {
        // Send message
        StreamWriter streamWriter = new StreamWriter(client.GetStream());
        streamWriter.Write(message);
        streamWriter.Flush();

        // Read response
        StreamReader streamReader = new StreamReader(client.GetStream());
        proxyResponse = streamReader.ReadToEnd();
    }
    catch (Exception ex)
    {
        // Ignore
    }

    return proxyResponse;
}

Кто-нибудь может заметить, что я делаю неправильно?

Edit:

Следуя предложению Ганса, которое он почему-то удалил, я попытался отправить «AUTHENTICATE \ n» вместо просто «AUTHENTICATE». Теперь я получаю сообщение об ошибке от Tor: «551 Неверная строка в кавычках. Вам нужно поставить пароль в двойные кавычки». По крайней мере, есть некоторый прогресс.

Затем я попытался отправить "AUTHENTICATE \" \ "\ n", как он хочет, но время ожидания истекло в ожидании ответа.

Edit:

Команда отлично работает в клиенте Windows Telnet. Мне даже не нужно добавлять цитаты. Не могу понять, что не так. Может быть, двойные кавычки неправильно кодируются при отправке?

Ответы [ 4 ]

8 голосов
/ 25 августа 2011
    public static void CheckIfBlocked(ref HtmlDocument htmlDoc, string ypURL, HtmlWeb hw)
    {
        if (htmlDoc.DocumentNode.InnerText.Contains("FORBIDDEN ACCESS!"))
        {
            Console.WriteLine("Getting Blocked");
            Utils.RefreshTor();
            htmlDoc = hw.Load(ypURL, "127.0.0.1", 8118, null, null);
            if (htmlDoc.DocumentNode.InnerText.Contains("FORBIDDEN ACCESS!"))
            {
                Console.WriteLine("Getting Blocked");
                Utils.RefreshTor();
            }
        }
    }
    public static void RefreshTor()
    {
        IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9051);
        Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            server.Connect(ip);
        }
        catch (SocketException e)
        {
            Console.WriteLine("Unable to connect to server.");
            RefreshTor();
            return;
        }

        server.Send(Encoding.ASCII.GetBytes("AUTHENTICATE \"butt\"\n"));
        byte[] data = new byte[1024];
        int receivedDataLength = server.Receive(data);
        string stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);

        if (stringData.Contains("250"))
        {
            server.Send(Encoding.ASCII.GetBytes("SIGNAL NEWNYM\r\n"));
            data = new byte[1024];
            receivedDataLength = server.Receive(data);
            stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
            if (!stringData.Contains("250"))
            {
                Console.WriteLine("Unable to signal new user to server.");
                server.Shutdown(SocketShutdown.Both);
                server.Close();
                RefreshTor();
            }
        }
        else
        {
            Console.WriteLine("Unable to authenticate to server.");
            server.Shutdown(SocketShutdown.Both);
            server.Close();
            RefreshTor();
        }
        server.Shutdown(SocketShutdown.Both);
        server.Close();
    }
4 голосов
/ 05 мая 2010

Когда я отправляю команду AUTHENTICATE, StreamReader читает ответ до конца, но конца нет, потому что в случае успеха поток остается открытым. Поэтому я изменил его, чтобы в данном случае прочитать только первую строку ответа.

public static string MakeTcpRequest(string message, TcpClient client, bool readToEnd)
{
    client.ReceiveTimeout = 20000;
    client.SendTimeout = 20000;
    string proxyResponse = string.Empty;

    try
    {
        // Send message
        using (StreamWriter streamWriter = new StreamWriter(client.GetStream()))
        {
            streamWriter.Write(message);
            streamWriter.Flush();
        }

        // Read response
        using (StreamReader streamReader = new StreamReader(client.GetStream()))
        {
            proxyResponse = readToEnd ? streamReader.ReadToEnd() : streamReader.ReadLine();
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }

    return proxyResponse;
}
1 голос
/ 01 октября 2015

Добавлен еще один пример, который я использую ниже. Также добавлены шаги для тех, кто хотел бы настроить Tor, который может принимать команды через порт управления.

Socket server = null;

//Authenticate using control password
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9151);
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Connect(endPoint);
server.Send(Encoding.ASCII.GetBytes("AUTHENTICATE \"your_password\"" + Environment.NewLine));
byte[] data = new byte[1024];
int receivedDataLength = server.Receive(data);
string stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);

//Request a new Identity
server.Send(Encoding.ASCII.GetBytes("SIGNAL NEWNYM" + Environment.NewLine));
data = new byte[1024];
receivedDataLength = server.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
if (!stringData.Contains("250"))
{
    Console.WriteLine("Unable to signal new user to server.");
    server.Shutdown(SocketShutdown.Both);
    server.Close();
}
else
{
    Console.WriteLine("SIGNAL NEWNYM sent successfully");
}

Шаги по настройке Tor:

  1. Копировать torrc-defaults в каталог, в котором находится tor.exe. Каталог по умолчанию, если вы используете браузер Tor: "~ \ Tor Browser \ Browser \ TorBrowser \ Data \ Tor"
  2. Открыть окно командной строки cmd
  3. chdir в каталог, где находится tor.exe. Каталог по умолчанию, если вы используете браузер Tor: "~ \ Tor Browser \ Browser \ TorBrowser \ Tor \"
  4. Создание пароля для доступа к порту управления Tor. tor.exe --hash-password “your_password_without_hyphens” | more
  5. Добавьте хэш пароля вашего пароля к torrc-defaults под ControlPort 9151. Он должен выглядеть примерно так: hashedControlPassword 16:3B7DA467B1C0D550602211995AE8D9352BF942AB04110B2552324B2507. Если вы принимаете ваш пароль как «пароль», вы можете скопировать строку выше.
  6. Теперь вы можете получить доступ к управлению Tor через Telnet после его запуска. Теперь код можно запустить, просто отредактируйте путь к папке, в которой находятся ваши файлы Tor. Тест модификации Tor через Telnet:
  7. Запустить tor с помощью следующей команды: tor.exe -f .\torrc-defaults
  8. Откройте другое приглашение cmd и введите: telnet localhost 9151
  9. Если все идет хорошо, вы должны увидеть полностью черный экран. Наберите «autenticate “your_password_with_hyphens”». Если все идет хорошо, вы должны увидеть «250 OK».
  10. Введите "SIGNAL NEWNYM", и вы получите новый маршрут, т.е. новый IP. Если все идет хорошо, вы должны увидеть «250 OK».
  11. Введите "setevents circ" (события цепи), чтобы включить консольный вывод
  12. Введите "getinfo circuit-status", чтобы увидеть токовые цепи
0 голосов
/ 21 февраля 2012

Возможно, вы используете Vidalia, которая генерирует хешированный пароль для доступа к порту управления. Вам необходимо использовать консольное приложение Tor и настроить файл torrc.

...