is there a wake on lan script using a web language preferably php that works? Also one that has some documentation on how to get it to work like what needs to be enabled on your server etc
function wol($broadcast, $mac)
{
$hwaddr = pack('H*', preg_replace('/[^0-9a-fA-F]/', '', $mac));
// Create Magic Packet
$packet = sprintf(
'%s%s',
str_repeat(chr(255), 6),
str_repeat($hwaddr, 16)
);
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if ($sock !== false) {
$options = socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, true);
if ($options !== false) {
socket_sendto($sock, $packet, strlen($packet), 0, $broadcast, 7);
socket_close($sock);
}
}
}
Should work - call it with a broadcast IP address, and a MAC address
I know this is an old questions, but it's still the first Google result, so here's what I ended up doing after a bit of research:
Prerequisites:
Linux box on the same network
Install the wakeonlan package from your system's package manager (i.e. sudo apt-get install wakeonlan)
Now the script is as easy as this:
<?php
# replace with your target MAC address
$mac = 'aa:bb:cc:11:22:33';
exec("wakeonlan $mac");
?>
Hope that helps someone.
HTML (test.htm)
<body>
Click to WOL XX:XX:XX:XX:XX:XX
</body>
PHP (test.php)
<?php
$mymac = $_REQUEST['mymac'];
wol("255.255.255.255", $mymac);
echo 'WOL sent to '.$mymac;
function wol($broadcast, $mac){
$mac_array = preg_split('#:#', $mac); //print_r($mac_array);
$hwaddr = '';
foreach($mac_array AS $octet){
$hwaddr .= chr(hexdec($octet));
}
//Magic Packet
$packet = '';
for ($i = 1; $i <= 6; $i++){
$packet .= chr(255);
}
for ($i = 1; $i <= 16; $i++){
$packet .= $hwaddr;
}
//set up socket
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if ($sock){
$options = socket_set_option($sock, 1, 6, true);
if ($options >=0){
$e = socket_sendto($sock, $packet, strlen($packet), 0, $broadcast, 7);
socket_close($sock);
}
}
} //end function wol
?>
Since the split() function was removed from PHP 7.0.0, this script uses preg_split() to be compatible with current and previous PHP versions.
Replace XX:XX:XX:XX:XX:XX in the HTML with your target MAC to test the script.
Building upon the previous answers. Had to set udp port to 9 and repeat the MAC a couple more times before it worked for me:
function wol($mac)
{
$hwaddr = pack('H*', preg_replace('/[^0-9a-fA-F]/', '', $mac));
// Create Magic Packet
$packet = sprintf(
'%s%s',
str_repeat(chr(255), 6),
str_repeat($hwaddr, 20)
);
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if ($sock !== false) {
$options = socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, true);
if ($options !== false) {
socket_sendto($sock, $packet, strlen($packet), 0, "255.255.255.255", 9);
socket_close($sock);
}
}
}
Please read if you're running PHP in Docker, otherwise disregard this.
It seems that UDP broadcast from docker isn't being routed properly (possibly only broadcasted in the container itself, not on the host).
You may try setting (CLI) --network host or (compose) network_mode: host, but for PHP this was causing issues.
You can't send UDP WoL messages directly, as the device you're trying to control is 'offline' it doesn't show up in your router's ARP table and thus the direct message can't be delivered.
I ended up running #reboot root /usr/bin/php -S 0.0.0.0:8877 -t /home/user/php and putting the wol.php file there.
As a 'more proper' solution you may run an 'wol proxy' docker container that does exactly that (but then in a network host privileged docker container).
Related
I send multicast via PHP (v7.0.8-5) this looking good so far.
My Problem is i am not able to receive the pakets.
CODE IS GOOD, working without Firewall
this is the code.
<?php
error_reporting(E_ALL | E_STRICT);
$mesg = "123456789012" ; //the msg i want to send
$ip = "228.5.6.7"; //the ip to send
$port = 14446 ; //the port to send
//build the socket
$grpparms = array("group"=>$ip,"interface"=>"eth0") ;
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_option($sock,IPPROTO_IP,MCAST_JOIN_GROUP,$grpparms);
if($argv[1] == 'r'){ //read multicasts
$from = '';
$dest_port = 0;
$binded = socket_bind($sock, '0.0.0.0',$port);
socket_recvfrom($sock, $buf, 12, 0, $from, $dest_port);
echo "Received $buf from remote address $from and remote port $dest_port" . PHP_EOL;
}
if ($argv[1] =='w'){ //write multicasts
socket_sendto($sock, $mesg, strlen($mesg), 0, $ip,$port);
echo "Send '$mesg' to $ip at port $port".PHP_EOL;
socket_close($sock) ;
}
?>
I call it with the paramter 'r' to read/receive and with 'w' to send/write multicasts.
I start this script over ssh on two different raspberrys (Vers. 2b) on the same switch. One with 'r' and the other with 'w'.
I can't test it myself right now, but change $dest_port in socket_recvfrom() to $port or change the value of $dest_port from 0 to 14446 and try again please.
I'm trying to scan an ip range and get info from specific devices.
Problem is, although i have SO_RCVTIMEO to array('sec'=>0,'usec'=>1000)
each request that should timeout gets around 0.5 seconds. The others on the other hand only take 0.005 seconds. You can imagine that if i want to scan a big IP range then i'm doomed.
What am i doing wrong or how can i improve it ?
Below is the code
foreach($ipArray as $ip){
$result = array();
$buf = '';
$from = '';
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,$timeout);
socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, 1);
//socket_bind($sock, $from, 2048);
socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, 0);
socket_sendto($sock, $data1, strlen($data1), 0, $ip, 10001);
$time = microtime(true);
if(!socket_recvfrom($sock, $buf, 512000, 0, $from, $port)){
echo (microtime(true) - $time) . ' elapsed<br><br><br>';
continue;
}
echo (microtime(true) - $time) . ' elapsed<br><br><br>';
$result= parse_result(bin2hex($buf));
socket_close($sock);
}
Note that i'm creating a separate socket for each IP because for some reason otherwise results would get confused in between the ips and i would sometimes get the same result twice.
Running this on a Windows Bitnami machine.
Thanks
Turns out Windows has a minimum amount of timeout you can set which is way higher than that on linux.
Basically the array('sec'=>0,'usec'=>1000) usec part of it only works in Linux machines.
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.
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;
}
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;
}
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
Try this :
echo exec('ping -n 1 -w 1 72.10.169.28');
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.
You can use exec function
exec("ping ".$ip);
here an example
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.
socket_create needs to be run as root on a UNIX system with;
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
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.
I am using the following piece of code in a php script to process incoming data over http and forward it to another module and waits for the response. It then closes the socket.
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock,$host,$port) or die("<?xml version=\"1.0\"?>");
if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) {
echo socket_strerror(socket_last_error($sock));
exit;
}
$arrOpt = array('l_onoff' => 1, 'l_linger' => 1);
socket_set_block($sock);
socket_set_option($sock, SOL_SOCKET, SO_LINGER, $arrOpt);
$address = gethostbyname($host);
$msg = $url;
$len = strlen($msg);
socket_sendto($sock, $msg, $len, 0, $remotehost, $remoteport) ;
socket_recvfrom($sock, $buff, 1000, 0, $host, $newport);
socket_close($sock);
The problem faced is that the response is received correctly and the socket_close error is also returning a success(output of socket_last_error). But after that if I do a netstat I see the port being in used and the process (output of /proc/pid/status) is in sleep state.
This behavior is random in nature and I am using PHP version 5.3.8 on a Amazon EC2 cloud.
its about TIME_WAIT ... to free the socket
in Linux run # /proc/sys/net/ipv4/tcp_fin_timeout to find out .... (default 60 sec)
more about
Hi I have a running socket server written with PHP.
The server is listening for connections.. any idea how my client(written in javascript) is going to connect to the server and send data to it?
PS: I only know how to connect a php client to the socket server but unsure how to connect a javascript client.
Thanks all for your time.
I use standard WebSocket API for client.
And core PHP socket for server side.
know, send and received data use a header on the browser with websocket. But the code PHP socket, send and received without header and just send plain data.
So we need to simulate header on the socketing server side.
For learning and know how do it, I write this clear sample code, With this code you can send a phrase to server and receive reverse phrase that in client.
server.php
<?php
//Code by: Nabi KAZ <www.nabi.ir>
// set some variables
$host = "127.0.0.1";
$port = 5353;
// don't timeout!
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0)or die("Could not create socket\n");
// bind socket to port
$result = socket_bind($socket, $host, $port)or die("Could not bind to socket\n");
// start listening for connections
$result = socket_listen($socket, 20)or die("Could not set up socket listener\n");
$flag_handshake = false;
$client = null;
do {
if (!$client) {
// accept incoming connections
// client another socket to handle communication
$client = socket_accept($socket)or die("Could not accept incoming connection\n");
}
$bytes = #socket_recv($client, $data, 2048, 0);
if ($flag_handshake == false) {
if ((int)$bytes == 0)
continue;
//print("Handshaking headers from client: ".$data."\n");
if (handshake($client, $data, $socket)) {
$flag_handshake = true;
}
}
elseif($flag_handshake == true) {
if ($data != "") {
$decoded_data = unmask($data);
print("< ".$decoded_data."\n");
$response = strrev($decoded_data);
socket_write($client, encode($response));
print("> ".$response."\n");
socket_close($client);
$client = null;
$flag_handshake = false;
}
}
} while (true);
// close sockets
socket_close($client);
socket_close($socket);
function handshake($client, $headers, $socket) {
if (preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $headers, $match))
$version = $match[1];
else {
print("The client doesn't support WebSocket");
return false;
}
if ($version == 13) {
// Extract header variables
if (preg_match("/GET (.*) HTTP/", $headers, $match))
$root = $match[1];
if (preg_match("/Host: (.*)\r\n/", $headers, $match))
$host = $match[1];
if (preg_match("/Origin: (.*)\r\n/", $headers, $match))
$origin = $match[1];
if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $headers, $match))
$key = $match[1];
$acceptKey = $key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
$acceptKey = base64_encode(sha1($acceptKey, true));
$upgrade = "HTTP/1.1 101 Switching Protocols\r\n".
"Upgrade: websocket\r\n".
"Connection: Upgrade\r\n".
"Sec-WebSocket-Accept: $acceptKey".
"\r\n\r\n";
socket_write($client, $upgrade);
return true;
} else {
print("WebSocket version 13 required (the client supports version {$version})");
return false;
}
}
function unmask($payload) {
$length = ord($payload[1]) & 127;
if ($length == 126) {
$masks = substr($payload, 4, 4);
$data = substr($payload, 8);
}
elseif($length == 127) {
$masks = substr($payload, 10, 4);
$data = substr($payload, 14);
}
else {
$masks = substr($payload, 2, 4);
$data = substr($payload, 6);
}
$text = '';
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i % 4];
}
return $text;
}
function encode($text) {
// 0x1 text frame (FIN + opcode)
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if ($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)$header = pack('CCS', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCN', $b1, 127, $length);
return $header.$text;
}
client.htm
<html>
<script>
//Code by: Nabi KAZ <www.nabi.ir>
var socket = new WebSocket('ws://localhost:5353');
// Open the socket
socket.onopen = function(event) {
var msg = 'I am the client.';
console.log('> ' + msg);
// Send an initial message
socket.send(msg);
// Listen for messages
socket.onmessage = function(event) {
console.log('< ' + event.data);
};
// Listen for socket closes
socket.onclose = function(event) {
console.log('Client notified socket has closed', event);
};
// To close the socket....
//socket.close()
};
</script>
<body>
<p>Please check the console log of your browser.</p>
</body>
</html>
Manual: first run php server.php on CLI and then open http://localhost/client.htm on browser.
You can see result:
http://localhost/client.htm
> I am the client.
< .tneilc eht ma I
php server.php
< I am the client.
> .tneilc eht ma I
Be careful it's just a sample code for test send and receive data, And it is not useful for executive work.
I suggest you use these projects:
https://github.com/ghedipunk/PHP-Websockets
https://github.com/esromneb/phpwebsocket
https://github.com/acbrandao/PHP/tree/master/ws
https://github.com/srchea/PHP-Push-WebSocket/
http://socketo.me/
And also I suggest you these articles for more details:
http://www.abrandao.com/2013/06/websockets-html5-php/
http://cuelogic.com/blog/php-and-html5-websocket-server-and-client-communication/
http://srchea.com/build-a-real-time-application-using-html5-websockets
Answering an old question in case people find it as I did via Google.
Nowadays nearly all contemporary browsers support the WebSocket Javascript API. Via WS it's possible for client JS in the browser to open full duplex sockets to severs written in PHP or other languages. The server must implement the WS protocol, but there are WS libraries now for PHP, Java, and other languages.
At this moment of writing, WS implementations still seem like a bit of a moving target, but, I'm currently working with WS/JS browser clients communicating with a WS/Java server and it does seem to be working.
Suggest Googling for WS implementations in your server language of choice.
Hope this helps!
I'm not aware of anything that provides arbitrary socket capabilities for JS. There is limited support for Web Sockets (which I think will require you to modify the server to conform to the space). Failing that, simple XHR might meet your needs (which would require that you modify the server to act as a web service). If the service runs on a different origin to the page, then you will need to use CORS or use a work around such as JSONP.
Try this:
http://code.google.com/p/phpwebsocket/
Shortly saying - you can't do that - it would be a security breach to let client side code open socket connections.
However, you could simulate that - send your data to another PHP page as an AJAX request, then make that PHP page communicate through the socket.
Update 2017:
In the mean time, websockets became a thing. Please note that the websocket protocol is a different thing than generic networking sockets