I work remotely and can access internal servers via VPN. When my VPN connection is established, I can reach my webserver via curl:
curl http://sub.mydomain.com
I can also reach the webserver in a browser by going to http://sub.mydomain.com
. So this does not seem to be a DNS issue with the webserver itself.
When developing my Laravel 4.2 application (PHP 5.6) served locally via Apache, however, php’s curl_exec
fails to resolve the host. Oddly, php’s gethostbyname($hostname)
correctly resolves the host. I have tried forcing IPv4 as I have read IPv6 can result in failures of this type with no success.
// works $ip = gethostbyname($hostname); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://$ip/path"); curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_exec($ch); // does NOT work $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://$hostname/path"); curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_exec($ch);
This leaves me at a loss. I don’t understand how PHP curl handles DNS resolution (clearly not with gethostbyname
). I also don’t understand exactly how DNS lookups on private networks work in the first place. So I really don’t know where to look to get PHP curl to resolve my private hosts.
Advertisement
Answer
Command line curl
resolved the host. Browser resolved the host. Only PHP curl failed to resolve it.
Ultimately, the issue came down to the curl configuration. I installed PHP with homebrew and as a dependency it installed curl-openssl
to be used by PHP. This install of curl is configured by the brew formula to use c-ares
for domain name resolution. I don’t know how c-ares
works, but this VPN DNS is apparently an edge case it does not handle correctly on OS X (perhaps due to OS X doing a lousy job of keeping /etc/resolv.conf
up to date).
/usr/bin/curl
on the other hand was configured to use the native OS X resolver. This is the same resolver used by PHP’s gethostbyname
and the web browser, which explains why both of those work as expected.
$ brew uninstall --ignore-dependencies curl-openssl
This resolved my issue by dumping this “broken” curl installation. I am not sure how the fallback mechanism works, but I believe PHP is now using /usr/bin/curl
since I have no other installations of curl
(that I know about) and the curl
version listed in phpinfo()
now matches /usr/bin/curl
when before it did not.