如何在PHP中手动解析HTTP(S)连接中的主机

如何在PHP中手动解析HTTP(S)连接中的主机,php,https,Php,Https,Curl有一个功能,可以手动指定解析主机的IP地址。例如: curl https://www.google.com --resolve "www.google.com:443:173.194.72.112" 这在使用HTTPS时特别有用。如果只是一个HTTP请求,我可以通过直接指定IP地址并添加主机头来实现同样的目的。但在HTTPS中,这将中断连接,因为SSL证书主机将与IP地址而不是主机头进行比较 我的问题是,如何在PHP中做同样的事情?根据,5.5.0中添加了对CURLOPT\u RESO

Curl有一个功能,可以手动指定解析主机的IP地址。例如:

curl https://www.google.com --resolve "www.google.com:443:173.194.72.112"
这在使用HTTPS时特别有用。如果只是一个HTTP请求,我可以通过直接指定IP地址并添加主机头来实现同样的目的。但在HTTPS中,这将中断连接,因为SSL证书主机将与IP地址而不是主机头进行比较

我的问题是,如何在PHP中做同样的事情?

根据,5.5.0中添加了对
CURLOPT\u RESOLVE
的支持。

请注意,在撰写本文时,它甚至还没有被记录下来,但根据它的说法,它以数组作为参数。

尽管@deceze的答案是正确的,但一个实例可能会有用。我需要
CURLOPT_RESOLVE
,因为我试图用一个额外的
主机:www.example.com
头直接连接到IP地址,但由于服务器使用SNI,所以无法工作

我用
CURLOPT_RESOLVE
来解决我的问题。此代码允许我通过选择的IP地址连接到SNI服务器:

$resolve = array(sprintf(
    "%s:%d:%s", 
    $hostname,
    $port,
    $host_ip
));

$ch = curl_init($url); 
curl_setopt($ch, CURLOPT_RESOLVE, $resolve);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
$result = curl_exec($ch); 
curl_close($ch);

尽管这是一个老问题,但值得注意的是,当使用
CURLOPT_RESOLVE
选项对多个服务器使用CURL时,需要在再次使用CURL之前清除DNS缓存,否则CURL将指向第一个服务器,而不管
CURL_setopt($ch,CURLOPT_RESOLVE,$RESOLVE)设置

唯一可行的方法是在
$resolve
数组中添加一个解析字符串,该字符串使用的最后一个服务器前缀为“-”:

$servers = [ '192.0.2.1', '192.0.2.2', '192.0.2.3' ];

foreach ($servers as $idx => $server) {

    $resolve = [];

    // Remove the last server used from the DNS cache
    if($idx){
        $last_server = $server[$idx-1];
        $resolve[] = "-example.com:443:{$last_server}";
    }

    // resolve the new server
    $resolve[] = "example.com:443:{$server}";

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 0);
    curl_setopt($ch, CURLOPT_RESOLVE, $resolve);
    curl_setopt($ch, CURLOPT_URL, "https://example.com/some/path");
    curl_setopt($ch, CURLOPT_VERBOSE, 1);

    $result = curl_exec($ch);
    $info = curl_getinfo($ch);

    echo $info['primary_ip']."\n";
    curl_close($ch);
}

正如这里所指出的:

可能
CURLOPT_IPRESOLVE
。。。!?From:“允许应用程序选择解析主机名时使用哪种类型的IP地址。这仅在使用使用多个IP版本解析地址的主机名时才有意义,可能的值为CURL_IPRESOLVE_where、CURL_IPRESOLVE_V4、CURL_IPRESOLVE_V6,默认情况下为CURL_IPRESOLVE_where。”。那不是我想要的。我想指定完整的IP地址。你说得对,我的错。