Как использовать протокол управления Tor в С#?
Я пытаюсь отправить команды в порт управления Tor программным образом, чтобы обновить цепочку. Я не смог найти примеры на С#, и мое решение не работает. Запрос истекает. У меня работает служба, и я вижу, как он прослушивает порт управления.
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. Мне даже не нужно добавлять кавычки. Не могу понять, что случилось. Возможно, двойные кавычки неправильно кодируются при отправке?
Ответы
Ответ 1
Когда я отправляю команду 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;
}
Ответ 2
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();
}
Ответ 3
Добавлен еще один пример, который я использую ниже. Также добавлены шаги для тех, кто хотел бы установить 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:
- Скопировать torrc-defaults в каталог, в котором находится tor.exe. Каталог по умолчанию, если вы используете браузер Tor: "~\Tor Browser\Browser\TorBrowser\Data\Tor"
- Откройте окно подсказки cmd
- chdir в каталог, где находится tor.exe. Каталог по умолчанию, если вы используете браузер Tor: "~\Tor Browser\Browser\TorBrowser\Tor \"
- Создайте пароль для доступа к управляющему порту Tor.
tor.exe --hash-password "your_password_without_hyphens" | more
- Добавьте хэш пароля пароля в torrc-defaults в ControlPort 9151. Он должен выглядеть примерно так:
hashedControlPassword 16:3B7DA467B1C0D550602211995AE8D9352BF942AB04110B2552324B2507
. Если вы принимаете свой пароль как "пароль", вы можете скопировать строку выше.
- Теперь вы можете получить доступ к управлению Tor через Telnet после его запуска. Теперь код может запускаться, просто отредактируйте путь к тому месту, где находятся файлы Tor в программе.
Проверка модификации Tor через Telnet:
- Запустите tor с помощью следующей команды:
tor.exe -f .\torrc-defaults
- Откройте следующую команду cmd и введите:
telnet localhost 9151
- Если все пойдет хорошо, вы должны увидеть полностью черный экран. Введите "
autenticate "your_password_with_hyphens"
" Если все пойдет хорошо, вы должны увидеть "250 OK".
- Введите "
SIGNAL NEWNYM
", и вы получите новый маршрут ergo new IP. Если все пойдет хорошо, вы должны увидеть "250 OK".
- Введите "
setevents circ
" (события схемы), чтобы включить вывод консоли.
- Введите "
getinfo circuit-status
", чтобы увидеть текущие цепи
Ответ 4
Возможно, вы используете Vidalia, который генерирует хешированный пароль для доступа к управляющему порту. Вам нужно использовать консольное приложение Tor и настроить файл torrc.