Curl has a feature for manually specifying which IP to resolve a host to. For example:
curl https://www.google.com --resolve "www.google.com:443:173.194.72.112"
This is especially useful when using HTTPS. If it was just a HTTP request, I could have achieved the same by specifying the IP address directly, and adding a host header. But in HTTPS that would break the connection since the SSL certificate host would be compared to the IP address and not the host header.
My question is, how can I do the same thing in PHP?
Although @deceze's answer is correct, a live example might be useful. I needed CURLOPT_RESOLVE
because I was trying to connect directly to the IP address with an additional Host: www.example.com
header, but since the server was using SNI, this didn't work.
I used CURLOPT_RESOLVE
to solve my problem. This code allows me to connect to the SNI server on a IP address of my choosing:
$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);
According to the changelog, support for CURLOPT_RESOLVE
was added in 5.5.0.
Note that at the time of writing it's not even documented yet, but according to this bug report it takes an array as argument.
Even though it's an old question is worth noticing that when using CURL to multiple servers using the CURLOPT_RESOLVE
option, there is a DNS cache which needs to be cleared before using CURL again, otherwise the CURL will point to the first server regardless of the curl_setopt($ch, CURLOPT_RESOLVE, $resolve);
setting.
The only way to make this work is to add to the $resolve
array a resolve string with the last sever used prefixed with a '-':
$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);
}
As pointed here: https://bugs.php.net/bug.php?id=74135
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With