46

I want a PHP script which allows you to ping an IP address and a port number (ip:port). I found a similar script but it works only for websites, not ip:port.

<?php

function ping($host, $port, $timeout) 
{ 
  $tB = microtime(true); 
  $fP = fSockOpen($host, $port, $errno, $errstr, $timeout); 
  if (!$fP) { return "down"; } 
  $tA = microtime(true); 
  return round((($tA - $tB) * 1000), 0)." ms"; 
}

//Echoing it will display the ping if the host is up, if not it'll say "down".
echo ping("www.google.com", 80, 10);

?>

I want this for a game server.

The idea is that I can type in the IP address and port number, and I get the ping response.

TRiG
  • 10,148
  • 7
  • 57
  • 107
user1288533
  • 463
  • 1
  • 4
  • 5
  • Use [socket connect](http://www.php.net/manual/en/function.socket-connect.php) or see if your server supports tcp:// urn – Panagiotis Mar 23 '12 at 15:13
  • 2
    ping uses ICMP: http://php.net/manual/en/function.socket-create.php – Marc B Mar 23 '12 at 15:14
  • @Panagiotis that's what he's doing... – Madara's Ghost Mar 23 '12 at 15:16
  • Ping can`t "ping port". Author possibly asks about measuring delay between request to a port made and answer received. The question itself is very confusing and must not have the tag "ping". Plus, server time to serve request may vastly vary in that case. I tried it for 80 port and it gives much more delay, than ICMP ping. This is true for other ports / services. Question has nothing common with network ping. Very confusing. – Eugene Zakharenko Nov 02 '20 at 14:20

9 Answers9

80

I think the answer to this question pretty much sums up the problem with your question.

If what you want to do is find out whether a given host will accept TCP connections on port 80, you can do this:

$host = '193.33.186.70'; 
$port = 80; 
$waitTimeoutInSeconds = 1; 
if($fp = fsockopen($host,$port,$errCode,$errStr,$waitTimeoutInSeconds)){   
   // It worked 
} else {
   // It didn't work 
} 
fclose($fp);

For anything other than TCP it will be more difficult (although since you specify 80, I guess you are looking for an active HTTP server, so TCP is what you want). TCP is sequenced and acknowledged, so you will implicitly receive a returned packet when a connection is successfully made. Most other transport protocols (commonly UDP, but others as well) do not behave in this manner, and datagrams will not be acknowledged unless the overlayed Application Layer protocol implements it.

The fact that you are asking this question in this manner tells me you have a fundamental gap in your knowledge on Transport Layer protocols. You should read up on ICMP and TCP, as well as the OSI Model.

Also, here's a slightly cleaner version to ping to hosts.

// Function to check response time
function pingDomain($domain){
    $starttime = microtime(true);
    $file      = fsockopen ($domain, 80, $errno, $errstr, 10);
    $stoptime  = microtime(true);
    $status    = 0;

    if (!$file) $status = -1;  // Site is down
    else {
        fclose($file);
        $status = ($stoptime - $starttime) * 1000;
        $status = floor($status);
    }
    return $status;
}
Community
  • 1
  • 1
ShadowScripter
  • 7,314
  • 4
  • 36
  • 54
  • Note: that is a quote from the linked question, please do not edit it away thinking it is a code formatting error. I usually put relevant quotations from links in my posts for historicity and in case of link rot, thank you! :) – ShadowScripter Feb 25 '13 at 18:13
21

In case the OP really wanted an ICMP-Ping, there are some proposals within the User Contributed Notes to socket_create() [link], which use raw sockets. Be aware that on UNIX like systems root access is required.

Update: note that the usec argument has no function on windows. Minimum timeout is 1 second.

In any case, this is the code of the top voted ping function:

function ping($host, $timeout = 1) {
    /* ICMP ping packet with a pre-calculated checksum */
    $package = "\x08\x00\x7d\x4b\x00\x00\x00\x00PingHost";
    $socket  = socket_create(AF_INET, SOCK_RAW, 1);
    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $timeout, 'usec' => 0));
    socket_connect($socket, $host, null);
    $ts = microtime(true);
    socket_send($socket, $package, strLen($package), 0);
    if (socket_read($socket, 255)) {
        $result = microtime(true) - $ts;
    } else {
        $result = false;
    }
    socket_close($socket);
    return $result;
}
user1931751
  • 594
  • 3
  • 13
  • 1
    The OP does explicitly state that he wants to use a port – icc97 Nov 12 '13 at 12:18
  • 1
    changed the $package var to $package = "\x08\x00\x19\x2f\x00\x00\x00\x00\x70\x69\x6e\x67"; got better results on windows when the IP timed out. This was from the documentation in your link. Thanks – PodTech.io May 09 '16 at 16:35
  • @icc97 OP might not know the difference between ICMP and TCP, so he might falsely assume that *some* port was necessary to ping. – Algoman Apr 16 '19 at 07:14
6

Test different ports:

$wait = 1; // wait Timeout In Seconds
$host = 'example.com';
$ports = [
    'http'  => 80,
    'https' => 443,
    'ftp'   => 21,
];

foreach ($ports as $key => $port) {
    $fp = @fsockopen($host, $port, $errCode, $errStr, $wait);
    echo "Ping $host:$port ($key) ==> ";
    if ($fp) {
        echo 'SUCCESS';
        fclose($fp);
    } else {
        echo "ERROR: $errCode - $errStr";
    }
    echo PHP_EOL;
}


// Ping example.com:80 (http) ==> SUCCESS
// Ping example.com:443 (https) ==> SUCCESS
// Ping example.com:21 (ftp) ==> ERROR: 110 - Connection timed out
Geo
  • 12,666
  • 4
  • 40
  • 55
5
function ping($ip){
    $output = shell_exec("ping $ip");
    var_dump($output);
}
ping('127.0.0.1');

UPDATE: If you pass an hardcoded IP (like in this example and most of the real-case scenarios), this function can be enough.

But since some users seem to be very concerned about safety, please remind to never pass user generated inputs to the shell_exec function: If the IP comes from an untrusted source, at least check it with a filter before using it.

T30
  • 11,422
  • 7
  • 53
  • 57
  • While this code may answer the question, it would be better to include some context, explaining how it works and when to use it. Code-only answers are not useful in the long run. – Bono Apr 23 '16 at 14:04
  • Well I like it! Simple and to the point. Does what the question asks. Put an IP in and get an output! – Adsy2010 Jun 07 '17 at 09:22
  • 3
    @Adsy2010 so do you know what will happen if my $ip is ``$ip = "-n 1 -w 1 localhost; rm -rf /home/;"`` in this case? – Frantisek Mar 25 '18 at 22:46
  • Which is why you would hardcode what goes in and out of the function... – Adsy2010 Mar 26 '18 at 09:06
  • 2
    @RichardRodriguez He's passing the argument straight from the source file, this is a hardcoded value. If you were accepting user input, your comment would be relevant, however, it is not. – brandito Jul 19 '18 at 04:31
5

Try this :

echo exec('ping -n 1 -w 1 72.10.169.28');
David Bélanger
  • 7,400
  • 4
  • 37
  • 55
  • 7
    exec is a dangerous function and should be disabled by default in your php.ini. – markus Mar 23 '12 at 15:18
  • 1
    what about the port where im gona put it – user1288533 Mar 23 '12 at 15:19
  • @markus-tharkun Agreed. But it is possible to protect it. If you are simply using an input such as an IP, transform IP to int and whatever and check it but yes it is true. – David Bélanger Mar 23 '12 at 15:23
  • 1
    But you don't need exec for this task. – markus Mar 23 '12 at 15:25
  • 2
    @markus what makes it dangerous? or is ONLY it if you pass user input to exec? – brandito Jul 19 '18 at 04:29
  • 1
    @Brandito not true. If an attacker somehow manages to run arbitrary php code, it can do a lot of damage with exec enabled (even if he is not a priviledged user it could excalate and become root). In a production environment it's safe only if disabled – Mauro F. Feb 03 '21 at 20:16
1

You can use exec function

 exec("ping ".$ip);

here an example

Jackie
  • 47
  • 1
  • 3
    exec is a dangerous function and should be disabled by default in your php.ini. – markus Mar 23 '12 at 15:17
  • 1
    you're right, but many time exec is the simple way to solve problems :D. For sure I must control and sanitize everything I will put in exec function. – Jackie Mar 23 '12 at 16:04
  • 4
    exec is only dangerous if you're crazy enough to blindly throw user input in there – Kenneth Wilke Oct 23 '14 at 01:36
  • @KennethWilke not true. If an attacker somehow manages to run arbitrary php code, it can do a lot of damage with exec enabled (even if he is not a priviledged user it could excalate and become root). In a production environment it's safe only if disabled – Mauro F. Feb 03 '21 at 20:16
0

socket_create needs to be run as root on a UNIX system with;

$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
kleopatra
  • 51,061
  • 28
  • 99
  • 211
PodTech.io
  • 4,874
  • 41
  • 24
0

You don't need any exec or shell_exec hacks to do that, it is possible to do it in PHP. The book 'You want to do WHAT with PHP?' by Kevin Schroeder, show's how.

It uses sockets and the pack() function which lets you read and write binary protocols. What you need to do is to create an ICMP packet, which you can do by using the 'CCnnnA*' format to create your packet.

markus
  • 40,136
  • 23
  • 97
  • 142
  • There's a whole bunch of suggestions of creating a ping via socket_create on the PHP [socket-create manual page usernotes](http://php.net/manual/en/function.socket-create.php#usernotes). However it does require root permissions in linux to run it. – icc97 Apr 16 '13 at 14:35
  • 4
    ONE BIG NOTE . to be able to create an ICMP packet in linux , you have to work with RAW sockets and packets , which needs administrative prevs . this means you need to run apache as root to be able to do that ! . it's safer to just exec then ! – Rami Dabain Apr 23 '13 at 04:24
-2

If you want to send ICMP packets in php you can take a look at this Native-PHP ICMP ping implementation, but I didn't test it.

EDIT:

Maybe the site was hacked because it seems that the files got deleted, there is copy in archive.org but you can't download the tar ball file, there are no contact email only contact form, but this will not work at archive.org, we can only wait until the owner will notice that sit is down.

jcubic
  • 61,973
  • 54
  • 229
  • 402