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

Я пытаюсь подключиться к скрытой службе 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, но он работает через командную строку.


person frosty    schedule 16.03.2013    source источник


Ответы (5)


Вам необходимо установить для параметра CURLOPT_PROXYTYPE значение CURLPROXY_SOCKS5_HOSTNAME, что, к сожалению, не был определен в старых версиях PHP, примерно до 5.6; если у вас есть ранее, но вы можете явно использовать его значение, равное 7:

curl_setopt($ch, CURLOPT_PROXYTYPE, 7);
person dr.scre    schedule 17.08.2013

Я использую 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
person FattyPotatoes    schedule 27.05.2013
comment
Это работает! Проверено как на Windows 10, так и на CentOS 6, также если Tor использует Socks 5 вместо Socks 4, используйте это: forward-socks5 / localhost:9150 . - person David Refoua; 18.05.2016
comment
мне нужны TOR и Privoxy, чтобы это работало? Благодарность - person ; 26.06.2018

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

curl_setopt($ch, CURLOPT_HEADER, 1); 
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); 
person Anthony Garcia-Labiad    schedule 04.04.2013

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 отсутствует точка с запятой.
  • В качестве значения адреса прокси-сервера задан URL-адрес HTTP, но его тип - 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');
person Meitar    schedule 30.03.2019

Вот простая функция, которая может вам помочь. Чтобы сэкономить время, прежде всего, вам нужно убедиться, что вы проверяете, действителен ли прокси, а не с помощью простой проверки с помощью fsocketopen ()

        try {
            $fp = fsockopen($ip, $port, $errno, $errstr, 10);
            fclose($fp);
            return true;
        } catch (\Throwable $th) {
            return false;
        }

Если сокет возвращает истину, перейдите к функции requestUrl

    private function requestUrl($url, $proxy)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_PROXY, $proxy);
        curl_setopt($curl, CURLOPT_HEADER, 1); 
        curl_setopt($curl, CURLOPT_HTTPPROXYTUNNEL, 1); 
        curl_setopt($curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        $contents = curl_exec($curl);
        //Check for errors.
        // if (curl_errno($curl)) {
        //     return new \Exception(curl_error($curl));
        // }
        curl_close($curl);
        return $contents;
    }
person Pushkraj Jori    schedule 24.06.2021