Monkuar Posted December 17, 2014 Share Posted December 17, 2014 function wsProcessClientMessage($clientID, $opcode, &$data, $dataLength) { global $wsClients; // check opcodes if ($opcode == WS_OPCODE_PING) { // received ping message return wsSendClientMessage($clientID, WS_OPCODE_PONG, $data); } elseif ($opcode == WS_OPCODE_PONG) { // received pong message (it's valid if the server did not send a ping request for this pong message) if ($wsClients[$clientID][4] !== false) { $wsClients[$clientID][4] = false; } } elseif ($opcode == WS_OPCODE_CLOSE) { // received close message if (substr($data, 1, 1) !== false) { $array = unpack('na', substr($data, 0, 2)); $status = $array['a']; } else { $status = false; } if ($wsClients[$clientID][2] == WS_READY_STATE_CLOSING) { // the server already sent a close frame to the client, this is the client's close frame reply // (no need to send another close frame to the client) $wsClients[$clientID][2] = WS_READY_STATE_CLOSED; } else { // the server has not already sent a close frame to the client, send one now wsSendClientClose($clientID, WS_STATUS_NORMAL_CLOSE); } wsRemoveClient($clientID); } elseif ($opcode == WS_OPCODE_TEXT || $opcode == WS_OPCODE_BINARY) { // received text or binary message if (function_exists('wsOnMessage')) wsOnMessage($clientID, $data, $dataLength, $opcode == WS_OPCODE_BINARY); } else { // unknown opcode return false; } return true; } Okay, this is the code that processes the client messages. It's extracted from here: http://code.google.com/p/phpwebsocket/ and I use it. My problem is. I call a mysql select on a function via my websockets using this: cb.socket.send('LOOTITEM 2213123'); (The CB class just connects it to the socket and sends it off) But I have a problem. I can crash my own server, just by going into Google Chromes console tab and spamming this: cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123');cb.socket.send('LOOTITEM 2213123'); Then I press enter, and look at my console. And a shit ton of queries are instantly checked and then it pops and says: So, this is way bad. Because people can just do this and crash the server. I need to limit the requests to atleast 1 second. Any idea? Link to comment https://forums.phpfreaks.com/topic/293144-rate-limiting-in-php-websockets/ Share on other sites More sharing options...
kicken Posted December 17, 2014 Share Posted December 17, 2014 Sounds like you have a bug in your wsBuildClientFrame function which is causing it to go into a recursion loop. You should address that issue before adding rate limiting. To add rate limiting, you count the # of requests along with keeping track of a timestamp. On each request compare the current # of requests to the # at the last timestamp and see if it's above your limit. If so, deny the request. Something like this //$lastTimestamp = timestamp of last check //$lastCount = whatever $count was at last check $now = time(); $count++; $timeDiff = $now - $lastTimestamp; if ($timeDiff > 1){ //Ensure timestamps have changed $countDiff = $count - $lastCount; $lastTimestamp = $now; $lastCount = $count; if ($countDiff/$timeDiff > 5){ //if more than 5 requests per second denyRequest(); } } Link to comment https://forums.phpfreaks.com/topic/293144-rate-limiting-in-php-websockets/#findComment-1499884 Share on other sites More sharing options...
Monkuar Posted December 18, 2014 Author Share Posted December 18, 2014 Sounds like you have a bug in your wsBuildClientFrame function which is causing it to go into a recursion loop. You should address that issue before adding rate limiting. To add rate limiting, you count the # of requests along with keeping track of a timestamp. On each request compare the current # of requests to the # at the last timestamp and see if it's above your limit. If so, deny the request. Something like this //$lastTimestamp = timestamp of last check //$lastCount = whatever $count was at last check $now = time(); $count++; $timeDiff = $now - $lastTimestamp; if ($timeDiff > 1){ //Ensure timestamps have changed $countDiff = $count - $lastCount; $lastTimestamp = $now; $lastCount = $count; if ($countDiff/$timeDiff > 5){ //if more than 5 requests per second denyRequest(); } } I see. And for the denyRequest function just simply return or exit out the user? And this issue wouldn't be prevalent if I were using a more modern approach, like socket.io/node.js correct? Link to comment https://forums.phpfreaks.com/topic/293144-rate-limiting-in-php-websockets/#findComment-1499944 Share on other sites More sharing options...
Monkuar Posted December 20, 2014 Author Share Posted December 20, 2014 Sounds like you have a bug in your wsBuildClientFrame function which is causing it to go into a recursion loop. You should address that issue before adding rate limiting. To add rate limiting, you count the # of requests along with keeping track of a timestamp. On each request compare the current # of requests to the # at the last timestamp and see if it's above your limit. If so, deny the request. Something like this //$lastTimestamp = timestamp of last check //$lastCount = whatever $count was at last check $now = time(); $count++; $timeDiff = $now - $lastTimestamp; if ($timeDiff > 1){ //Ensure timestamps have changed $countDiff = $count - $lastCount; $lastTimestamp = $now; $lastCount = $count; if ($countDiff/$timeDiff > 5){ //if more than 5 requests per second denyRequest(); } } Sorry to bump this thread, but I got a working version: function wsOnMessage($clientID, $message, $messageLength, $binary) { global $servername, $dbuser, $dbpassword, $dbname, $users, $db; // anti flood protection if($_SESSION['last_session_request'] > time() - 1){ // users will be redirected to this page if it makes requests faster than 2 seconds echo "Limit Reached... Simmer down!"; return false; }else{ echo $_SESSION['last_session_request']; } I got a working version working here: My question is: That return false works but it will stop the whole script? Which if other users are using will stop them as well right? How do I only target the specific client and user instead? Also, should I use microtime instead? You know, I can use "wsClose($clientID);" to kick them off. But what's stopping them from just refreshing? Link to comment https://forums.phpfreaks.com/topic/293144-rate-limiting-in-php-websockets/#findComment-1500207 Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.