Como posso me conectar a um serviço oculto do Tor usando cURL em PHP?

366

Estou tentando conectar-me a um serviço oculto do Tor usando o seguinte código 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);

Quando o executo, recebo o seguinte erro:

Não foi possível resolver o nome do host

No entanto, quando executo o seguinte comando na minha linha de comando no Ubuntu:

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

Eu recebo uma resposta como esperado

A documentação do PHP cURL diz o seguinte:

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

Eu acredito que o motivo pelo qual ele funciona na linha de comando é porque o Tor (o proxy) está resolvendo o nome de host .onion, que ele reconhece. Ao executar o código PHP acima, meu palpite é que cURL ou PHP está tentando resolver o nome de host .onion e não o reconhece. Procurei uma maneira de dizer ao cURL / PHP para permitir que o proxy resolvesse o nome do host, mas não consigo encontrar uma maneira.

Há uma pergunta muito semelhante ao Stack Overflow, a solicitação cURL usando o proxy socks5 falha ao usar o PHP, mas funciona através da linha de comando .

gelado
fonte

Respostas:

21

Eu uso Privoxy e cURL para raspar páginas do 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);
?>

Depois de instalar o Privoxy, você precisa adicionar esta linha ao arquivo de configuração ( /etc/privoxy/config). Observe o espaço e '.' um fim de linha.

forward-socks4a / localhost:9050 .

Em seguida, reinicie o Privoxy.

/etc/init.d/privoxy restart
FattyPotatoes
fonte
Isso funciona! Testado no Windows 10 e no CentOS 6, também se o Tor usar as meias 5 em vez das meias 4, use o seguinte:forward-socks5 / localhost:9150 .
David Refoua
preciso do TOR e do Privoxy para que isso funcione? graças
8

Tente adicionar isto:

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

TL; DR: defina CURLOPT_PROXYTYPEpara usar CURLPROXY_SOCKS5_HOSTNAMEse você tiver um PHP moderno, 7caso contrário o valor e / ou corrija o CURLOPT_PROXYvalor.

Como você deduziu corretamente, não é possível resolver .oniondomínios pelo sistema DNS normal, porque esse é um domínio de nível superior reservado especificamente para uso do Tor e esses domínios por design não têm endereços IP para os quais mapear.

O uso CURLPROXY_SOCKS5direcionará o comando cURL para enviar seu tráfego ao proxy, mas não fará o mesmo para a resolução de nomes de domínio. As solicitações de DNS, que são emitidas antes que o cURL tente estabelecer a conexão real com o site Onion, ainda serão enviadas ao resolvedor de DNS normal do sistema. Essas solicitações de DNS certamente falharão, porque o resolvedor de DNS normal do sistema não saberá o que fazer com um .onionendereço, a menos que também esteja encaminhando especificamente essas consultas para o Tor.

Em vez de CURLPROXY_SOCKS5, você deve usar CURLPROXY_SOCKS5_HOSTNAME. Como alternativa, você também pode usar CURLPROXY_SOCKS4A, mas o SOCKS5 é muito preferido. Qualquer um desses tipos de proxy informa ao cURL para realizar suas pesquisas de DNS e sua transferência de dados real via proxy. Isso é necessário para resolver com êxito qualquer .oniondomínio.

Há também dois erros adicionais no código na pergunta original que ainda precisam ser corrigidos pelos comentaristas anteriores. Esses são:

  • Ponto e vírgula ausente no final da linha 1.
  • O valor do endereço de proxy está definido como um URL HTTP, mas seu tipo é SOCKS; estes são incompatíveis. Para proxies do SOCKS, o valor deve ser uma combinação de IP ou nome de domínio e número da porta sem um esquema / protocolo / prefixo.

Aqui está o código correto na íntegra, com comentários para indicar as alterações.

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

Você também pode omitir CURLOPT_PROXYTYPEtotalmente a configuração alterando o CURLOPT_PROXYvalor para incluir o socks5h://prefixo:

// 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
fonte