Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I protect my Meteor server from an infinite loop on the client?

I've run into a situation where an infinite loop on the client is crashing the Meteor server. The infinite loop is a bug that I will fix, and not the subject of this question. My concern is that a malicious user could create their own infinite loop and crash the Meteor server.

The infinite loop in question is repeatedly making calls to Meteor.subscribe(...) and Meteor.call(...). It looks like these requests are being queued on the server to the point of incapacitation, even though the client's intention was to abandon them. Is there a way to tell the server that the request has been abandoned and to remove it from the queue?

I suppose this wouldn't protect the server from a client that makes thousands of successive requests without abandoning them, so that question would supersede this one if anyone has an answer to it. How can I limit the number of requests that can be made by a single client?

In these APM charts, you can see how the infinite loop affected performance. I started it at about 13:17, and at 13:25 the app crashed (terminated by Heroku for exceeding its memory quota).

Meteor APM charts - kadira.io - client infinite loop causes server crash

like image 534
colllin Avatar asked Jan 09 '15 20:01

colllin


1 Answers

When Meteor.subscribe is called, the Meteor.publish function is executed on the server. You can thus decides in the publish function not to serve the data.

It depends if you expect you users to be logged in or not to serve the data. If you expect the users to be logged in, you can create a collection registering any call to the publish function (ie any client subscription request) with the userID used. You would ask this collection any time a logged user attempts to subscribe and check if this user has been making multiple requests recently. If this client hits you're defined request quota, you can just return null.

You can do the same with non logged in users by using the https://github.com/gadicc/meteor-headers package and registering the IP adress.

You can do the same within the server methods that are repeatedly called by the client meteor.call().

I think that checking in this database (which would stay small as only the recent connection has to be kept in the database) and to decide to serve the data or not would be less time consuming that serving the data everytime.

I hope this helps.

like image 156
Hugo Avatar answered Oct 19 '22 05:10

Hugo