Jak mogę połączyć się z usługą ukrytą Tora za pomocą cURL w PHP?

366

Próbuję połączyć się z usługą ukrytą Tora za pomocą następującego kodu 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);

Po uruchomieniu pojawia się następujący błąd:

Nie można rozpoznać nazwy hosta

Jednak po uruchomieniu następującego polecenia z wiersza polecenia w systemie Ubuntu:

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

Otrzymuję odpowiedź zgodnie z oczekiwaniami

Dokumentacja PHP cURL mówi:

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

Uważam, że powodem, dla którego działa z wiersza poleceń, jest to, że Tor (proxy) rozwiązuje nazwę hosta .onion, którą rozpoznaje. Kiedy uruchamiam powyższy kod PHP, domyślam się, że cURL lub PHP próbuje rozwiązać nazwę hosta .onion i nie rozpoznaje go. Szukałem sposobu, aby cURL / PHP pozwolił proxy rozpoznać nazwę hosta, ale nie mogę znaleźć sposobu.

Istnieje bardzo podobne pytanie o przepełnienie stosu, żądanie cURL przy użyciu proxy socks5 kończy się niepowodzeniem podczas korzystania z PHP, ale działa przez wiersz poleceń .

mroźny
źródło

Odpowiedzi:

21

Używam Privoxy i cURL do zeskrobywania stron Tora:

<?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);
?>

Po zainstalowaniu Privoxy musisz dodać ten wiersz do pliku konfiguracyjnego ( /etc/privoxy/config). Zwróć uwagę na spację i „.” koniec linii.

forward-socks4a / localhost:9050 .

Następnie uruchom ponownie Privoxy.

/etc/init.d/privoxy restart
Ziemniaki
źródło
To działa! Testowany zarówno na Windows 10, jak i CentOS 6, także jeśli Tor używa Socks 5 zamiast Socks 4, użyj tego:forward-socks5 / localhost:9150 .
David Refoua
czy potrzebuję TOR i Privoxy, aby to zadziałało? dzięki
AMB
8

Spróbuj dodać to:

curl_setopt($ch, CURLOPT_HEADER, 1); 
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); 
Anthony Garcia-Labiad
źródło
5

TL; DR: Ustaw, CURLOPT_PROXYTYPEaby użyć, CURLPROXY_SOCKS5_HOSTNAMEjeśli masz nowoczesny PHP, w 7przeciwnym razie wartość i / lub popraw CURLOPT_PROXYwartość.

Jak prawidłowo wywnioskowałeś, nie możesz rozpoznać .oniondomen za pomocą normalnego systemu DNS, ponieważ jest to zarezerwowana domena najwyższego poziomu przeznaczona specjalnie do użytku przez Tora, a takie domeny z założenia nie mają adresów IP, na które można by mapować.

Użycie CURLPROXY_SOCKS5spowoduje skierowanie polecenia cURL do wysłania ruchu do serwera proxy, ale nie zrobi tego samego w przypadku rozpoznawania nazw domen. Żądania DNS, które są wysyłane, zanim cURL spróbuje ustanowić faktyczne połączenie z witryną Onion, nadal będą wysyłane do normalnego systemu rozpoznawania nazw DNS w systemie. Te żądania DNS z pewnością się nie powiodą, ponieważ normalny system rozpoznawania nazw DNS w systemie nie będzie wiedział, co zrobić z .onionadresem, chyba że on również specjalnie przekieruje takie zapytania do Tora.

Zamiast tego CURLPROXY_SOCKS5musisz użyć CURLPROXY_SOCKS5_HOSTNAME. Możesz także użyć CURLPROXY_SOCKS4A, ale SOCKS5 jest znacznie bardziej preferowany. Każdy z tych typów proxy informuje cURL, aby przeprowadzał zarówno wyszukiwanie DNS, jak i faktyczny transfer danych przez proxy. Jest to wymagane do pomyślnego rozwiązania dowolnej .oniondomeny.

Istnieją również dwa dodatkowe błędy w kodzie w pierwotnym pytaniu, które nie zostały jeszcze naprawione przez poprzednich komentujących. To są:

  • Brak średnika na końcu wiersza 1.
  • Wartość adresu proxy jest ustawiona na adres URL HTTP, ale jej typ to SOCKS; te są niezgodne. W przypadku serwerów proxy SOCKS wartością musi być kombinacja adresu IP lub nazwy domeny i numeru portu bez schematu / protokołu / prefiksu.

Oto poprawny kod w całości z komentarzami wskazującymi zmiany.

<?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);

Możesz także CURLOPT_PROXYTYPEcałkowicie pominąć ustawienie , zmieniając CURLOPT_PROXYwartość tak, aby zawierała socks5h://prefiks:

// 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
źródło