Localhost != 127.0.0.1?
Friday 20th November, 2009 15:06 Comments: 1
At least that's what PHP 5.3.1 seems to think. I tried upgrading a system that was running PHP from 5.3.0 to 5.3.1 and several parts of several websites broke. I narrowed it down to anything that was trying to do database access, which made me investigate the extensions and libraries (which were fine). So I decided to look more closely (locally, using php-cgi from the command prompt so I could see all the errors) and I discovered that the errors were caused by PHP's inability to access the MySQL server. The MySQL server was running fine, which I already knew because PHP 5.3.0 was happy, as were other services that depend on MySQL working correctly. Here's the error message that was returned:
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
How to replicate this? Simple, try the following:
<?php
$dbhost = ("localhost");
$dbname = ("dbname");
$dbuser = ("dbuser");
$dbpass = ("dbpass");
@$dbh=mysql_connect ("$dbhost", "$dbuser", "$dbpass") or die (mysql_error());
?>
But if you change "localhost" to "127.0.0.1" you get:
Access denied for user 'dbuser'@'localhost' (using password: YES)
If I'd used valid credentials, I wouldn't get the access denied error, but I'm not going to tell you any usernames and passwords!
So does anyone know why PHP 5.3.1 isn't able to resolve localhost as 127.0.0.1? Or is this perhaps some kind of IPv6 quirk, as MySQL is only listening on an IPv4 address, but PHP 5.3.1 might be trying an IPv6 address? I can't see many references to DNS changes in the PHP changelog, except perhaps this:
Improved dns_get_record() AAAA support on windows. Always available when IPv6 is support is installed, format is now the same than on unix.
Perhaps that's the cause?
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
How to replicate this? Simple, try the following:
<?php
$dbhost = ("localhost");
$dbname = ("dbname");
$dbuser = ("dbuser");
$dbpass = ("dbpass");
@$dbh=mysql_connect ("$dbhost", "$dbuser", "$dbpass") or die (mysql_error());
?>
But if you change "localhost" to "127.0.0.1" you get:
Access denied for user 'dbuser'@'localhost' (using password: YES)
If I'd used valid credentials, I wouldn't get the access denied error, but I'm not going to tell you any usernames and passwords!
So does anyone know why PHP 5.3.1 isn't able to resolve localhost as 127.0.0.1? Or is this perhaps some kind of IPv6 quirk, as MySQL is only listening on an IPv4 address, but PHP 5.3.1 might be trying an IPv6 address? I can't see many references to DNS changes in the PHP changelog, except perhaps this:
Improved dns_get_record() AAAA support on windows. Always available when IPv6 is support is installed, format is now the same than on unix.
Perhaps that's the cause?
Robert - Sunday 22nd November, 2009 12:46
It seems that PHP are aware of this quirk, and it does appear that Windows (or the user) is probably to blame as localhost is apparently resolving to an IPv6 and an IPv4 address, and PHP only tries the IPv6 address:
http://bugs.php.net/bug.php?id=45150
So it looks like editing the hosts file to comment out the IPv6 address should fix the issue (but would potentially break anything else that expects localhost to resolve to a service that's only listening on IPv6, which admittedly isn't very likely). I guess we need to stop using localhost and start using IPv4 and IPv6 IP addresses (until IPv4 goes away, which won't be for a very long time).
http://bugs.php.net/bug.php?id=45150
So it looks like editing the hosts file to comment out the IPv6 address should fix the issue (but would potentially break anything else that expects localhost to resolve to a service that's only listening on IPv6, which admittedly isn't very likely). I guess we need to stop using localhost and start using IPv4 and IPv6 IP addresses (until IPv4 goes away, which won't be for a very long time).