Chrooted PHP-FPM script cannot resolve DNS after a moment
Asked Answered
Q

1

21

I need some help to understand why a PHP-FPM chrooted PHP script fails to resolve an FQDN few instants after the PHP-FPM service started.

When I (re)start the PHP-FPM service, it works (resolution succeeds) a few seconds and then resolution fails.

I chrooted a PHP application (a WordPress actually) via PHP-FPM (settings `` chroot` in the PHP-FPM pool configuration file) and gave PHP what it needed:

  • A basic /etc/hosts file
  • A mount --bind of /etc/ssl/certs
  • A /dev/urandom (via mknod)
  • A mount --bind of /usr/share/zoneinfo
  • A mount --bind of /var/run/mysqld for the socket to MySQL.
  • A mount --bind of /var/run/nscd for the socket to nscd resolver.
  • A place to store PHP sessions

I noticed the issue when WordPress complained it could not download updates with:

stream_socket_client(): php_network_getaddresses: getaddrinfo failed: Name or service not known stream_socket_client(): unable to connect to tcp://www.wordpress.org:80 (php_network_getaddresses: getaddrinfo failed: Name or service not known)

Sample script:

<?php
$domain = 'www.example.com';
echo 'gethostbynamel(): '; var_dump(gethostbynamel($domain));
echo 'checkdnsrr(): ';     var_dump(checkdnsrr($domain, 'A'));
echo 'dns_get_record(): '; var_dump(dns_get_record($domain));
?>

When it works:

gethostbynamel(): array(1) {
  [0]=>
  string(13) "93.184.216.34"
}
checkdnsrr(): bool(true)
dns_get_record(): array(1) {
  [0]=>
  array(5) {
    ["host"]=>
    string(15) "www.example.com"
    ["class"]=>
    string(2) "IN"
    ["ttl"]=>
    int(86348)
    ["type"]=>
    string(1) "A"
    ["ip"]=>
    string(13) "93.184.216.34"
  }
}

After a few instants:

gethostbynamel(): bool(false)
checkdnsrr(): bool(true)
dns_get_record(): array(1) {
  [0]=>
  array(5) {
    ["host"]=>
    string(15) "www.example.com"
    ["class"]=>
    string(2) "IN"
    ["ttl"]=>
    int(86400)
    ["type"]=>
    string(1) "A"
    ["ip"]=>
    string(13) "93.184.216.34"
  }
}

Note that, in any case, both dns_get_record() and checkdnsrr() always works fine.

Three questions:

  1. What makes dns_get_record() and checkdnsrr() achieve to resolve FQDN when gethostbynamel() fails?
  2. What does gethostbynamel() need in a chrooted setup?
  3. What could make it works only for a few moment?

Software versions:

  • Debian 9
  • Nginx 10.3
  • PHP 7.0.19

Thanks

Queer answered 20/12, 2017 at 23:25 Comment(6)
You need /etc/host.conf and /etc/nsswitch.conf in the chroot jail.Gran
I added /etc/host.conf, /etc/nsswitch.conf and /etc/resolv.conf but the issue persists. Running sysdig (not on a chrooted instance because I fail to use sysdig on the PHP-FPM) shows the gethostbynamel() only uses /etc/resolv.conf (stat res=0 path=/etc/resolv.conf) where both dns_get_record() and checkdnsrr() uses the network (sendto fd=3(<4u>127.0.0.1:47531->127.0.0.1:domain) size=33 tuple=NULL).Queer
This dns lookups only half working in chroot mailing-list thread confirms that "PHP's gethostbyname() is a wrapper for the system call of the same name". Following this Chroot and resolv.conf other mailing-list thread, I added /lib/x86_64-linux-gnu/libnss_dns.so.2 into the jail (keeping the two files you gave) and it seems to work for now (resolving more than 5 minutes is way longer it never did).Queer
@Queer Thank you so much for that comment. I've been banging my head against the wall trying to figure out why my chroot jail isn't resolving stuff, but those libraries were what I was missing and fixed my issue right away :)Forepleasure
It may not be your issue, but its usually a good idea to give DNS lookups a fully qualified domain (ending with a "."). You could try "www.example.com." vs. "www.example.com" on your net - do an nslookup -d2 on both, and the results will generally favor the dot at the end - without that, it may try to resolve it as a subdomain first, and there are a number of issues which that can cause depending on your network configuration.Bulimia
If you ended up figuring this out you should post an answer.Shelia
M
4

Per the comment on the question, Chrooted PHP-FPM script cannot resolve DNS after a moment, the OP was able to resolve the issue by adding the following files to the jail:

  • /lib/x86_64-linux-gnu/libnss_dns.so.2 (or depending on OS variant, /lib/libnss_dns.so )
  • /etc/nsswitch.conf
  • /etc/resolv.conf
Margoriemargot answered 3/10, 2020 at 5:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.