Как я могу подключиться к скрытому сервису Tor, используя cURL в PHP?

366

Я пытаюсь подключиться к скрытому сервису Tor, используя следующий код PHP:

$url = 'http://jhiwjjlqpyawmpjx.onion/'
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PROXY, "http://127.0.0.1:9050/");
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
$output = curl_exec($ch);
$curl_error = curl_error($ch);
curl_close($ch);

print_r($output);
print_r($curl_error);

Когда я запускаю его, я получаю следующую ошибку:

Не удалось разрешить имя хоста

Однако, когда я запускаю следующую команду из моей командной строки в Ubuntu:

curl -v --socks5-hostname localhost:9050 http://jhiwjjlqpyawmpjx.onion

Я получаю ответ, как и ожидалось

Документация PHP cURL гласит:

--socks5-hostname
Use  the  specified  SOCKS5 proxy (and let the proxy resolve the host name).

Я считаю, что причина, по которой он работает из командной строки, заключается в том, что Tor (прокси-сервер) разрешает имя хоста .onion, которое он распознает. Когда я запускаю код PHP выше, я предполагаю, что cURL или PHP пытаются определить имя хоста .onion и не распознают его. Я искал способ сказать cURL / PHP, чтобы прокси разрешил имя хоста, но я не могу найти способ.

Существует очень похожий вопрос переполнения стека: запрос cURL с использованием прокси socks5 не выполняется при использовании PHP, но он работает через командную строку .

морозный
источник

Ответы:

21

Я использую Privoxy и cURL для очистки страниц Tor:

<?php
    $ch = curl_init('http://jhiwjjlqpyawmpjx.onion'); // Tormail URL
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
    curl_setopt($ch, CURLOPT_PROXY, "localhost:8118"); // Default privoxy port
    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
    curl_exec($ch);
    curl_close($ch);
?>

После установки Privoxy вам необходимо добавить эту строку в файл конфигурации ( /etc/privoxy/config). Обратите внимание на пробел и «.» конец строки.

forward-socks4a / localhost:9050 .

Затем перезапустите Privoxy.

/etc/init.d/privoxy restart
FattyPotatoes
источник
Это работает! Протестировано на Windows 10 и CentOS 6, также если Tor использует Socks 5 вместо Socks 4, используйте это:forward-socks5 / localhost:9150 .
Дэвид Рефуа
мне нужно TOR и Privoxy, чтобы это работало? спасибо
8

Попробуйте добавить это:

curl_setopt($ch, CURLOPT_HEADER, 1); 
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); 
Энтони Гарсия-Лабиад
источник
5

TL; DR: установите CURLOPT_PROXYTYPEдля использования, CURLPROXY_SOCKS5_HOSTNAMEесли у вас есть современный PHP, в 7противном случае значение и / или исправьте CURLOPT_PROXYзначение.

Как вы правильно поняли, вы не можете разрешить .onionдомены через обычную систему DNS, потому что это зарезервированный домен верхнего уровня, специально предназначенный для использования Tor, и такие домены по своей конструкции не имеют IP-адресов для сопоставления.

Использование CURLPROXY_SOCKS5будет направлять команду cURL для отправки своего трафика на прокси, но не будет делать то же самое для разрешения доменного имени. Запросы DNS, которые отправляются до того, как cURL попытается установить фактическое соединение с сайтом Onion, будут по-прежнему отправляться обычному преобразователю DNS системы. Эти DNS-запросы, несомненно, будут терпеть неудачу, потому что обычный системный DNS-распознаватель не будет знать, что делать с .onionадресом, если он также не будет специально направлять такие запросы в Tor.

Вместо этого CURLPROXY_SOCKS5вы должны использовать CURLPROXY_SOCKS5_HOSTNAME. Кроме того, вы также можете использовать CURLPROXY_SOCKS4A, но SOCKS5 гораздо предпочтительнее. Любой из этих типов прокси информирует cURL о выполнении поиска DNS и фактической передачи данных через прокси. Это необходимо для успешного разрешения любого .onionдомена.

В исходном вопросе есть также две дополнительные ошибки в коде, которые еще не были исправлены предыдущими комментаторами. Эти:

  • Отсутствует точка с запятой в конце строки 1.
  • Значением адреса прокси-сервера является HTTP-URL, но его типом является SOCKS; это несовместимо. Для SOCKS-прокси значение должно быть комбинацией IP-адреса или имени домена и номера порта без схемы / протокола / префикса.

Вот правильный код в полном объеме, с комментариями, чтобы указать изменения.

<?php
$url = 'http://jhiwjjlqpyawmpjx.onion/'; // Note the addition of a semicolon.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PROXY, "127.0.0.1:9050"); // Note the address here is just `IP:port`, not an HTTP URL.
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); // Note use of `CURLPROXY_SOCKS5_HOSTNAME`.
$output = curl_exec($ch);
$curl_error = curl_error($ch);
curl_close($ch);

print_r($output);
print_r($curl_error);

Вы также можете CURLOPT_PROXYTYPEполностью пропустить настройку , изменивCURLOPT_PROXY значение, включив socks5h://префикс:

// Note no trailing slash, as this is a SOCKS address, not an HTTP URL.
curl_setopt(CURLOPT_PROXY, 'socks5h://127.0.0.1:9050');
Meitar
источник