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


cURL request using socks5 proxy fails when using PHP, but it works through the command line

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

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被更改为公共页面,例如谷歌,则请求成功,每个人都很高兴。

如果发生任何更改,则连接需要SSH隧道。正如命令行请求成功所证明的那样,隧道是开放的并且正在运行。

这里有没有明显遗漏的东西?

您需要将选项CURLOPT_PROXYTYPE设置为CURLPROXY_SOCKS5_HOSTNAME,遗憾的是,这在大约5.6之前的旧PHP版本中没有定义;如果您在前面有,但您可以显式使用其值,该值等于7:

curl_setopt($ch, CURLOPT_PROXYTYPE, 7);

在选项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开始就可用,所以你可以简单地使用它。

相关文章: