如何在PHP中使用cURL连接到Tor隐藏服务?


366

我正在尝试使用以下PHP代码连接到Tor隐藏服务:

$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让代理解析主机名,但是我找不到方法。

有一个非常相似的Stack Overflow问题,使用PHP时使用socks5代理进行的cURL请求失败,但可通过命令行运行

Answers:



21

我使用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

这可行!在Windows 10和CentOS 6上都进行了测试,如果Tor使用的是Socks 5而不是Socks 4,请使用:forward-socks5 / localhost:9150 .
David Refoua,2016年

我需要同时使用TOR和Privoxy才能工作吗?谢谢
AMB


5

TL; DR:如果您拥有现代PHP,则设置CURLOPT_PROXYTYPE为;否则CURLPROXY_SOCKS5_HOSTNAME为该值7,并且/或者更正该CURLOPT_PROXY值。

正确推论,您无法.onion通过普通的DNS系统解析域,因为这是专门供Tor使用的保留的顶级域,并且此类域在设计上没有IP地址可映射到。

使用CURLPROXY_SOCKS5将指示cURL命令将其流量发送到代理,但对于域名解析则不会这样做。 cURL尝试建立与Onion站点的实际连接之前发出的DNS请求仍将发送到系统的常规DNS解析器。这些DNS请求肯定会失败,因为系统的普通DNS解析器将不知道如何.onion处理地址,除非它也专门将此类查询转发给Tor。

而是CURLPROXY_SOCKS5必须使用CURLPROXY_SOCKS5_HOSTNAME。或者,您也可以使用CURLPROXY_SOCKS4A,但是SOCKS5是更可取的。这两种代理类型都可以通知cURL通过代理执行其DNS查找和实际数据传输。这是成功解析任何.onion域所必需的。

原始问题中的代码中还有两个其他错误,以前的评论者尚未纠正。这些是:

  • 第1行末尾缺少分号。
  • 代理地址值设置为HTTP URL,但是其类型为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');
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.