User Contributed Notes 31 notes

Sometimes when using $_SERVER['HTTP_X_FORWARDED_FOR'] OR $_SERVER['REMOTE_ADDR'] more than 1 IP address is returned, for example '155.240.132.261, 196.250.25.120'. When this string is passed as an argument for gethostbyaddr() PHP gives the following error: Warning: Address is not a valid IPv4 or IPv6 address in...

To work around this I use the following code to extract the first IP address from the string and discard the rest. (If you wish to use the other IPs they will be in the other elements of the $ips array).

The problem of broken DNS servers was causing me a problem because i had a page for user statistics that required around 20 reverse dns lookups to be done, and even as many as 5/6 of them being broken was causing a huge delay in loading the page. so i wrote a function that uses a UDP socket to talk directly to the DNS server (instead of going via the normal gethostbyaddr function) this let me set a timeout.

The only requirement is that your DNS server must be able to do recursive lookups, it wont go to other DNS servers if its told to... and of course you need to know your DNS servers IP address :-)

This could be expanded quite a bit and improved but it works and i've seen quite a few people trying various methods to achieve something like this so i decided to post it here. on most servers it should also be more efficient than other methods such as calling nslookup because it doesn't need to run external programs

Note: I'm more a C person than a PHP person, so just ignore it if anything hasn't been done the *recomended* way :-)

If all else fails, but you have shell access, Unix/Linux servers can use this for a timeout response:

shell_exec('host -W 2 0.0.0.0');

Where 0.0.0.0 is of course the IP, and '2' is the number of seconds for the timeout. This returns a more detailed string of info, with some additional text which might vary depending on the system, so if you want a string with the hostname and nothing else, you'll have to do some substring cutting. There should be an equivalent of 'host' for Windows users to execute, but it isn't my platform.

You should be careful in the use of $_SERVER['HTTP_X_FORWARDED_FOR'], as I discovered, once using Amazon AWS's Elastic Load Balancer's, this value may be a comma separated list of IP addresses and will thusly not compare as conceived in almost every example I have seen posted by users in the comments.

tried out some of the examples below, but no one worked for me.("host" returns something if domain-name wasn't found"gethostbyaddr" has a too long timeout when it fails"the udp-example" returns some strange characters...)so i have changed the "host"-example a little bit. hope someone can need it. (maybe with little changes like without error-description)

I just spent a dickens of a time trying to figure out why my gethostbyaddr's were simply failing halfway through.

I'm returning a log of page visits, and with each new IP, I wanted to pull the hostname of the IP. On each report page, I'm pulling 500 lines from my Db, but only maybe 25 IPs on average. Sometimes this report would generate in under 15 seconds, other times it would fail with a connection reset.

It turns out that several of the IPs in my Db looked like this: x.255.x.x. gethostbyaddr really hates that and simply dies when it reaches one of these IPs.

For my case, I purged the Db and prevented the logging of IPs that contain 255.

Just to fun that gethostbyadd() returns server machine name known in LAN rather then its DNS if I try to call it against my own host (from workstation), whether it would local (behind the proxy) or global (of proxy itself) IP or just loop 127.0.0.1.

And thus you can get LAN names of other workstations by its intranet IPs (I mean smth like 192.168.0.???)

If you need to store an IP addresses in a database, you can convert and store it in an INT type column (4 bytes). The functions below can convert IP addresses to its integer decimal value and vice-versa.

I previously used something very similar to what god@weaponzero.f2s.com posted but found it to be quite tedious for getting the 'nicehost'. This method below is a lot cleaner, and it also works for numeric addresses.

Be cautious when looking up many hostnames. If your DNS server is slow to respond, you may have to pump up your Max execution time for your scripts, otherwise, it will timeout. I found that even 3 unresolvable hosts can cause a 30 second delay in processing.

Turning on the HostnameLookup function on in the apache configuration file will severely increase the loading times of all the pages serviced by the httpd-server.It's mostly a better idea to just use gethostbyaddr($REMOTE_ADDR); instead of $REMOTE_HOST if you turned HostnameLookups On, unless you want the hostnames specified in apache's log file...

I have observed that there are problems with all approaches that use the existence of an IP address to verify that the name being looked up actually exists.

If you're using opendns, then a request to a non-existent server returns an IP address anyway, the address being one for an opendns server. This is process is presumably in place so that errant URLs in browser requests take you to a "legitimate" page, i.e, the openDNS website where they can notify you of a problem.

Unfortunately, that mechanism seems to occur for ANY non-existent hostname. Appending a single period to the hostname does not seem to help.

If you use gethostbyaddr() with a bad IP address then it will send an error message to the error log.
If you don't want your error log file getting too big then first check that the IP address is valid.

In the following example I first check if the IP number starts with a number,
if not then don't use gethostbyaddr('..')

Be careful with the usage of this function - it will slow down a server to a crawl if called a lot and the slowness won't be reflected in any of the obvious places, like CPU usage, apache requests, SQL etc. When you do use it make a special note of where!