Search code examples
phpmysqlpdodns

How to prevent Reverse DNS Lookup with PDO-connect per IP-address?


I try to connect via PDO to another database server (MySQL) per IP-address.

$db = new PDO('mysql:host=IP-ADDRESS;dbname=AAA', 'USER', 'XXXXX');

I faked IP-address and user here, this is not the error ;)

But for whatever reason, PDO is going to make some crazy reverse DNS lookups and ends up connecting to a completely different server, which has another IP-address and other domains assigned per A-records as the reverse dns lookup from PDO will find here.

PDO throws the specific exception:

SQLSTATE[28000] [1045] Access denied for user 'USER'@'WWW.ANOTHER-SERVER.COM'

While connecting in the terminal via mysql-client, everything is working as expected.

  1. How can I avoid that PDO makes a reverse DNS lookup?
  2. How can I tell PDO that it should connect per IP-address given in the parameters ?
  3. How can it be, that this reverse DNS lookup is so wrong ?

There are no specific entries in /etc/hosts, which could be the root cause for that.


Solution

  • PHP/PDO machine:

    PDO will never to a reverse lookup. It will do a forward lookup, and then connect to that IP.

    You should be able to see that, being root at the PHP/PDO machine, running

    tcpdump -i ethsomething -n -s 1500 -xX port 3306
    

    Which IP number is shown here when the PDO tries to connect?

    MySQL machine:

    MySQL will never know what the host name was under which you tried to reach it. The server will see an incoming request, do a getpeername() on the socket, yielding an IP number.

    The server will then do a reverse lookup of that IP by default. You can turn this off by putting

    [mysqld]
    skip-name-resolve
    

    into your my.cnf file and restarting the server.

    When MySQL is configured to do the reverse lookup, it will try to do so. If that fails, it will take 5 to 30 seconds on a connect attempt waiting for a DNS response before the server gives up.

    If the reverse lookup succeeds, MySQL will go into the mysql.user tables and its friends with a resolved name, user@reverse_lookup_result.

    If the reverse lookup fails, or has been disabled with skip-name-resolve, MySQL will go into the mysql.user tables and friends with an unresolved name, user@1.2.3.4 or similar.

    That has interesting consequences:

    1. When name-resolve is on, a user may have different privileges depending on the success of the reverse lookup.

    2. When skip-name-resolve is on, entries that are not ip-numbers in mysql.user.host are useless.