簡體   English   中英

如何在PHP中手動解析HTTP(S)連接中的主機

[英]How to manually resolve hosts in HTTP(S) connections in PHP

Curl具有手動指定要將主機解析到的IP的功能。 例如:

curl https://www.google.com --resolve "www.google.com:443:173.194.72.112"

這在使用HTTPS時特別有用。 如果它只是一個HTTP請求,我可以通過直接指定IP地址並添加主機頭來實現相同的目的。 但是在HTTPS中會破壞連接,因為SSL證書主機將與IP地址而不是主機頭進行比較。

我的問題是,我怎樣才能在PHP中做同樣的事情?

雖然@ deceze的答案是正確的,但實際的例子可能會有用。 我需要CURLOPT_RESOLVE因為我試圖使用額外的Host: 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);

根據更改日志 ,在5.5.0中添加了對CURLOPT_RESOLVE支持。
請注意,在編寫本文時,它甚至尚未記錄,但根據此錯誤報告 ,它將數組作為參數。

即使這是一個老問題值得注意的是,當使用CURLOPT_RESOLVE選項將CURL用於多個服務器CURLOPT_RESOLVE ,需要在再次使用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);
}

正如此處所指出: https//bugs.php.net/bug.php?id = 74135

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM