Avatar ·

Подключение к Tor скрытому сервису через cURL в PHP: пошаговое руководство

Всем привет! Я новичок в PHP и пытаюсь написать скрипт, который обращается к сайту в сети Tor (.onion). Поднял локально Tor Browser, он работает, через него захожу на сайты. Но когда пытаюсь сделать запрос через cURL в PHP, ничего не выходит. Вот мой код: ```php ``` Но получаю ошибку: «Couldn't resolve host name». Пробовал менять порт на 9150 (как в Tor Browser) — та же история. Tor Browser точно запущен, сайт открывается в браузере. Что я делаю не так? Может, нужно какие-то дополнительные заголовки или настройки DNS? Я слышал про SOCKS5 прокси, но, видимо, не так его настроил. Буду благодарен за подробное объяснение. <<>>

Проблема: DNS-резолвинг через Tor

Ваша основная ошибка — типична для новичков. Вы указали CURLOPT_PROXY и CURLOPT_PROXYTYPE, но забыли самый важный параметр: CURLOPT_PROXYTYPE нужно ставить CURLPROXY_SOCKS5_HOSTNAME, а не просто CURLPROXY_SOCKS5. Разница критична:

  • CURLPROXY_SOCKS5 — отправляет DNS-запросы на локальный резолвер (ваш системный DNS). Адрес .onion не может быть разрешён обычным DNS, поэтому ошибка «Couldn't resolve host name».
  • CURLPROXY_SOCKS5_HOSTNAME — передаёт разрешение DNS самому SOCKS5-прокси (Tor). Tor резолвит .onion через свою сеть.

Правильное решение

Вот исправленный код, который гарантированно работает с Tor (порт по умолчанию для Tor-демона — 9050, для Tor Browser — 9150):

<?php
$url = 'http://example.onion/';
$torProxy = '127.0.0.1:9050'; // или '127.0.0.1:9150' для Tor Browser

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PROXY, $torProxy);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME); // КЛЮЧЕВОЙ МОМЕНТ!
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Разрешаем редиректы
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Для .onion HTTPS (необязательно, но часто нужно)
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // Тайм-аут для медленных соединений

$response = curl_exec($ch);

if (curl_error($ch)) {
    echo 'Ошибка cURL: ' . curl_error($ch);
} else {
    echo 'Ответ получен: ' . substr($response, 0, 500);
}
curl_close($ch);
?>

Дополнительные настройки и пояснения

  • Проверьте, какой порт слушает Tor:
    • Если вы запустили tor как службу (демон) — порт 9050.
    • Если используете Tor Browser — порт 9150 (SOCKS5-прокси браузера).
  • CURLOPT_FOLLOWLOCATION — многие .onion сайты делают редиректы, без этой опции вы получите пустой ответ.
  • CURLOPT_SSL_VERIFYPEER — для HTTPS .onion сайтов (например, https://facebookcorewwwi.onion/) часто нужен false, так как сертификаты самоподписанные или не соответствуют домену.
  • CURLOPT_TIMEOUT — Tor-сеть может быть медленной, но без тайм-аута скрипт зависнет навсегда.

Проверка работы Tor

Чтобы убедиться, что ваш скрипт действительно использует Tor, можно запросить https://check.torproject.org/ через тот же прокси:

<?php
$checkUrl = 'https://check.torproject.org/';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $checkUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:9050');
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
$result = curl_exec($ch);
curl_close($ch);

if (strpos($result, 'Congratulations') !== false) {
    echo 'Tor работает!';
} else {
    echo 'Прокси не активен или неверный порт.';
}
?>

Важные замечания безопасности

  • Не используйте CURLOPT_SSL_VERIFYPEER = false в продакшене без необходимости — это снижает безопасность.
  • Убедитесь, что ваш PHP имеет поддержку cURL и SOCKS (проверьте phpinfo()).
  • Если Tor запущен на другой машине, укажите её IP вместо 127.0.0.1.
<<>>

Альтернатива: использование библиотеки Artax или Guzzle с прокси

Если вы предпочитаете объектно-ориентированный подход или работаете с современными фреймворками, можно использовать GuzzleHttp — популярную HTTP-библиотеку для PHP. Вот пример подключения к Tor через Guzzle:

<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Handler\CurlHandler;

$handler = new CurlHandler();
$stack = HandlerStack::create($handler);

$client = new Client([
    'handler' => $stack,
    'curl' => [
        CURLOPT_PROXY => '127.0.0.1:9050',
        CURLOPT_PROXYTYPE => CURLPROXY_SOCKS5_HOSTNAME,
    ],
    'timeout' => 30,
    'verify' => false, // Для .onion HTTPS
]);

try {
    $response = $client->get('http://example.onion/');
    echo $response->getBody()->getContents();
} catch (Exception $e) {
    echo 'Ошибка: ' . $e->getMessage();
}
?>

Когда это полезно?

  • Вы используете Laravel, Symfony или другой фреймворк, где Guzzle уже встроен.
  • Нужна более гибкая обработка ошибок, повторные попытки, асинхронные запросы.
  • Хотите избежать ручной настройки cURL-опций.

Важно: Убедитесь, что установили Guzzle через Composer: composer require guzzlehttp/guzzle. Прокси-опции передаются через массив curl в конфигурации клиента.

Оба подхода (чистый cURL и Guzzle) работают одинаково хорошо, но Guzzle даёт более читаемый код и лучшую интеграцию с современным PHP.