使用 PHP 时使用 socks5 代理的 cURL 请求失败,但它通过命令行工作

Posted

技术标签:

【中文标题】使用 PHP 时使用 socks5 代理的 cURL 请求失败,但它通过命令行工作【英文标题】:cURL request using socks5 proxy fails when using PHP, but it works through the command line 【发布时间】:2013-02-03 08:12:30 【问题描述】:

cURL + 代理菜鸟在这里,很难。我在尝试通过代理从远程安全服务器检索网页时遇到问题。远程开发人员显然已经正确设置了一切,因此以下命令行指令可以正常工作并返回我们正在寻找的内容:

curl -k --socks5-hostname localhost:xxxx https://hostname/

但是,以下 php 不会回显所请求的网页。相反,它会回显错误“无法解析主机名”:

$proxy = 'localhost:xxxx';
$url = 'https://hostname/';
//$proxyauth = 'user:password';

$ch = curl_init();
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
//curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyauth);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_URL, $url);
$curl_scraped_page = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);

if ($error)
    echo $error;
elseif ($curl_scraped_page)
    echo $curl_scraped_page;

如果$url改成公共页面,比如google,请求成功,大家开心。

如果有任何改变,则连接需要 SSH 隧道。隧道已打开且正常运行,命令行请求成功证明了这一点。

这里有什么明显的遗漏吗?

【问题讨论】:

【参考方案1】:

您需要将选项CURLOPT_PROXYTYPE 设置为CURLPROXY_SOCKS5_HOSTNAME,可悲的是wasn't defined in old PHP versions, circa pre-5.6;如果你之前有,但你可以显式使用它的值,它等于7

curl_setopt($ch, CURLOPT_PROXYTYPE, 7);

【讨论】:

【参考方案2】:

在选项CURLOPT_PROXYTYPE 中,您需要设置CURLPROXY_SOCKS5_HOSTNAME 选项而不是CURLPROXY_SOCKS5。 在这种情况下,DNS 查询(用于解析主机名)将被发送到 SOCKS 代理,而不是在本地网络中解析。

curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);

这个常量从 PHP 5.5.23 和 PHP 5.6.7 和 cURL 7.18.0 开始可用,所以你可以简单地使用它。

【讨论】:

这解决了我的错误 "can't complete socks5 connection to 0000:0000:0000:0000:0000:0000:0000:0000"

以上是关于使用 PHP 时使用 socks5 代理的 cURL 请求失败,但它通过命令行工作的主要内容,如果未能解决你的问题,请参考以下文章

怎样设置socks代理

如何正确认识socks5代理ip

如何通过 socks5 为 PHP 制作代理流?

使用 urllib2、socks5 代理和 socksipy 时超时不起作用

虚拟机中使用本机的socks5代理

iOS 使用socks5代理服务器