Reputation: 71
I came across a strange question about php curl.
It will connect to the DNS server to resolve, even though the host is in /etc/hosts !
software version:
Server : CentOS release 6.3 (Final)
Linux Curl version : curl --version curl 7.47.1 (x86_64-pc-linux-gnu) libcurl/7.47.1 OpenSSL/1.0.1e zlib/1.2.3 libidn/1.18 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp Features: IDN IPv6 Largefile NTLM NTLM_WB SSL libz UnixSockets`
PHP version : php -v PHP 5.4.41 (cli) (built: Aug 11 2015 22:29:40) Copyright (c) 1997-2014 The PHP Group Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
PHP curl version : php -r "var_export(curl_version());" array ( 'version_number' => 471040, 'age' => 3, 'features' => 952221, 'ssl_version_number' => 0, 'version' => '7.48.0', 'host' => 'x86_64-redhat-linux-gnu', 'ssl_version' => 'OpenSSL/1.0.1e', 'libz_version' => '1.2.3',
server configurations:
/etc/hosts : 127.0.0.1 lalala.examplekkk.com
/etc/resolv.conf : nameserver 8.8.8.8
/etc/nsswitch.conf hosts: files dns
commands execution results:
PING lalala.examplekkk.com (127.0.0.1) 56(84) bytes of data. 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.041 ms 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.035 ms ....
strace php -r '$curl=curl_init();$url="http://lalala.examplekkk.com";curl_setopt($curl,CURLOPT_URL,$url);$content=curl_exec($curl);echo $content;' ... open("/etc/hosts", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=1308, ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f85c7b5c000 read(3, "127.0.0.1 localhost localhost."..., 4096) = 1308 ... fcntl(3, F_SETFD, FD_CLOEXEC) = 0 connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, 16) = 0 sendto(3, "\177{\1\0\0\1\0\0\0\0\0\0\6lalala\nexamplekkk\3c"..., 39, MSG_NOSIGNAL, NULL, 0) = 39 poll([{fd=3, events=POLLIN|POLLRDNORM}], 1, 0) = 0 (Timeout) ...
I am confused that why the php curl need to connect to dns server to resolve the host name??
I execute the command 'strace curl 'http://lalala.examplekkk.com', and is all right without connecting to 8.8.8.8.
Is it a bug in php-curl ?
Upvotes: 1
Views: 2248
Reputation: 1222
Summary: the CURLOPT_RESOLVE
is the solution to your issue.
From https://curl.haxx.se/libcurl/c/CURLOPT_RESOLVE.html:
Provide custom host name to IP address resolves.
In case of the PHP implementation, you have to supply an array with at least one element. cURL only looks at the array values, not the keys.
Each single name resolve string should be written using the format HOST:PORT:ADDRESS[,ADDRESS]... where HOST is the name libcurl will try to resolve, PORT is the port number of the service where libcurl wants to connect to the HOST and ADDRESS is one or more numerical IP addresses.
Here is a more complete example using your values:
$curl = curl_init();
$options = [
CURLOPT_RESOLVE => ['lalala.examplekkk.com:80:127.0.0.1'],
CURLOPT_URL => "http://lalala.examplekkk.com/",
CURLOPT_RETURNTRANSFER => 1,
];
curl_setopt_array($curl, $options);
$content = curl_exec($curl);
It's not a bug, it is well-documented behavior.
As far a I know, you cannot tell cURL to use the /etc/hosts
file. If this is incorrect, please leave a comment.
Upvotes: 0