Identify Remote OS By IP Address In PHP


Read {count} times since 2020

In the recent post, I gave the default TTL value of different devices. As you can see, when you ping a host you can roughly identify the operating system the remote server’s running. I saw a question on Stack Overflow about this. Sadly it was down voted and was removed later. I tested if it is possible and I found that it is possible.

In this post, I will give a function that automatically pings the remote host and find out the possible Operating Systems the remote server is running. For this, we have a **JSON **file that contains the TTL of different devices / OSs.

Note that the remote server with the IP Address should be online the time the checking is done. Otherwise pinging the host will fail.

Get JSON Data

I made the JSON file and is available at this URL. This JSON file is needed for the identification of the device. Here is how an item in the JSON file looks like :

{
 "device" : "Linux",
 "version" : "2.0.x kernel",
 "protocol" : "ICMP",
 "ttl" : "64"
}

It contains the TTL value, the device name and its version. Also the protocol which is not needed necessarily.

detectOs($ip)

Now, let’s get to the function that identifies the OS. It’s an easy function that needs the following :

  • IP Address
  • JSON file with the name “ttlValues.txt” on the same directory as the file containing the function
  • shell_exec function to execute (PHP Safe Mode should be Off)

We use the ping command to ping the remote IP address and get the TTL. This is the function code :

function detectOs($ip, $returnArray=true){
 if(filter_var($ip, FILTER_VALIDATE_IP)){
  $cmd="ping -c 2 $ip";
  $shell=shell_exec($cmd);
  preg_match("/ttl=(.*?)stime/", $shell, $m);
  if(isset($m[1])){
   $ttl=$m[1];
   $list=file_get_contents("./ttlValues.txt");
   $list=json_decode($list, true);
   $oses=array();
   if($ttl==64){$oses[]="Mostly A *nix Device (Linux, Unix etc..)";}
   if($ttl==128){$oses[]="Mostly A Windows Device";}
   if($ttl==254){$oses[]="Mostly A Solaris/AIX Device";}
   foreach($list as $vals) {
    if($vals['ttl']==$ttl){
     $oses[]=$vals['device']." ".$vals['version'];
    }
   }
   return $returnArray===true ? $oses:implode(",", $oses);
  }else{
   return "connectionFailed";
  }
 }else{
  return "invalidIP";
 }
}

You can change the location of the JSON file by replacing the file path “./ttlValues.txt”. The function will return either one of the following :

<td>
  If the IP address given is not valid
</td>
<td>
  If the pinging failed or TTL value wasn&#8217;t accessbile
</td>
invalidIP
connectionFailed

If either one of the following didn’t return, then the return value is an array. You have the option to decide whether the return output should be an array or a string of possible devices separated by “,”.

Also, if the hops between the connection of your machine and the remote server is too much, it’s better to widen the search by, replacing the following code in the function

if($vals['ttl']==$ttl)

to :

if($vals['ttl']<=$ttl)

Usage

$os=detectOs("127.0.0.1"); // Localhost OS, please
if($os=="invalidIP"){
 echo "Invalid IP address";
}elseif($os=="connectionFailed"){
 echo "Unable to connect to external server";
}else{
 echo "<br/>The Operating System Can Be one of the following : <ul>";
 foreach($os as $v){
  echo "<li>$v</li>";
 }
 echo "</ul>";
}

The above code checks all the return values of the function and finally output the array of possible devices.

You can also output string instead of array :

echo detectOs("127.0.0.1", false);

The above sample code will output something like this :

Linux 2.2.14 kernel,MacOS/MacTCP 2.0.x,NetBSD

Simple usage, right ? Well, use it for your own various purposes.