Comment puis-je me connecter à un service caché Tor en utilisant cURL en PHP?

366

J'essaie de me connecter à un service caché Tor en utilisant le code PHP suivant:

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

Lorsque je l'exécute, j'obtiens l'erreur suivante:

Impossible de résoudre le nom d'hôte

Cependant, lorsque j'exécute la commande suivante à partir de ma ligne de commande dans Ubuntu:

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

Je reçois une réponse comme prévu

La documentation PHP cURL dit ceci:

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

Je crois que la raison pour laquelle cela fonctionne à partir de la ligne de commande est que Tor (le proxy) résout le nom d'hôte .onion, qu'il reconnaît. Lors de l'exécution du code PHP ci-dessus, je suppose que cURL ou PHP essaie de résoudre le nom d'hôte .onion et ne le reconnaît pas. J'ai cherché un moyen de dire à cURL / PHP de laisser le proxy résoudre le nom d'hôte, mais je ne trouve pas de moyen.

Il y a une question de débordement de pile très similaire, la demande cURL utilisant le proxy socks5 échoue lors de l'utilisation de PHP, mais cela fonctionne via la ligne de commande .

glacial
la source

Réponses:

21

J'utilise Privoxy et cURL pour gratter les pages 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);
?>

Après avoir installé Privoxy, vous devez ajouter cette ligne au fichier de configuration ( /etc/privoxy/config). Notez l'espace et '.' a la fin de la ligne.

forward-socks4a / localhost:9050 .

Redémarrez ensuite Privoxy.

/etc/init.d/privoxy restart
FattyPotatoes
la source
Cela marche! Testé sur Windows 10 et CentOS 6, même si Tor utilise Socks 5 au lieu de Socks 4, utilisez ceci:forward-socks5 / localhost:9150 .
David Refoua
ai-je besoin de TOR et Privoxy pour que cela fonctionne? merci
8

Essayez d'ajouter ceci:

curl_setopt($ch, CURLOPT_HEADER, 1); 
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); 
Anthony Garcia-Labiad
la source
5

TL; DR: paramétré CURLOPT_PROXYTYPEpour utiliser CURLPROXY_SOCKS5_HOSTNAMEsi vous avez un PHP moderne, la valeur 7sinon, et / ou corriger la CURLOPT_PROXYvaleur.

Comme vous l'avez correctement déduit, vous ne pouvez pas résoudre les .oniondomaines via le système DNS normal, car il s'agit d' un domaine de premier niveau réservé spécifiquement pour une utilisation par Tor et ces domaines par conception n'ont aucune adresse IP à mapper.

L'utilisation CURLPROXY_SOCKS5dirigera la commande cURL pour envoyer son trafic vers le proxy, mais ne fera pas de même pour la résolution des noms de domaine. Les requêtes DNS, qui sont émises avant que cURL ne tente d'établir la connexion réelle avec le site Onion, seront toujours envoyées au résolveur DNS normal du système. Ces demandes DNS échoueront sûrement, car le résolveur DNS normal du système ne saura pas quoi faire avec une .onionadresse à moins qu'il ne transmette également spécifiquement ces requêtes à Tor.

Au lieu de CURLPROXY_SOCKS5, vous devez utiliser CURLPROXY_SOCKS5_HOSTNAME. Alternativement, vous pouvez également utiliser CURLPROXY_SOCKS4A, mais SOCKS5 est de loin préféré. L'un ou l'autre de ces types de proxy informe cURL d'effectuer à la fois ses recherches DNS et son transfert de données réel via le proxy. Cela est nécessaire pour résoudre avec succès n'importe quel .oniondomaine.

Il y a également deux erreurs supplémentaires dans le code de la question d'origine qui n'ont pas encore été corrigées par les commentateurs précédents. Ceux-ci sont:

  • Point-virgule manquant à la fin de la ligne 1.
  • La valeur de l'adresse proxy est définie sur une URL HTTP, mais son type est SOCKS; ce sont incompatibles. Pour les proxys SOCKS, la valeur doit être une combinaison IP ou nom de domaine et numéro de port sans schéma / protocole / préfixe.

Voici le code correct dans son intégralité, avec des commentaires pour indiquer les changements.

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

Vous pouvez également omettre CURLOPT_PROXYTYPEcomplètement le paramètre en modifiant la CURLOPT_PROXYvaleur pour inclure le socks5h://préfixe:

// 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
la source