Drupal Performance Tips: Prevent spam bots from posting to your Drupal site and prevent server loads due to repeated posts

Zyxware default image4

One of the Drupal sites we maintain had recently started slowing down considerably in spite of the site mostly being static and in spite of boost set up on the server. On examination of the site we found that two things were happening on the site. One was that the site was being crawled indiscriminately by rogue crawlers. This we solved using the DDOS deflate script and setting DDOS deflate to run every 10 seconds. The second problem was that there were some bots which were continuously sending POST requests to /comment/cid/reply pages. For this we had to come up with a workaround.

We added the following snippet of code in the settings.php to take care of the problem. This requires that you have memcache set up on the server. If you don't have memcache you will probably have to use some alternative caching system to handle this.

if ($_SERVER["REQUEST_METHOD"] == 'POST' && !isset($_COOKIE['DRUPAL_UID'])) {
  $m = new Memcached();
  $m->addServer('localhost', 11211);
  $key = 'anon_'. $_SERVER['REMOTE_ADDR'];
  if (!$m->get($key)) {
    $m->set($key, 1, 5);
  }
  else {
    $m->set($key, 1, 5);
    echo ("We are sorry, there was an error processing your submission. Please try after some time");
    exit;
  }
}

The snippet does two things - it checks if the request is a POST request and if the user is an anonymous user, then it sets a key in memcache which will act as a auto decaying flag to indicate that the IP had sent a POST request in the last 5 seconds. If the same IP tries to send another POST request within this 5 second period the snippet returns an error and exists. The error is sent out instead of the header("HTTP/1.1 418 I'm a teapot"); response because the snippet can possibly catch regular users from a single network trying to post to the site within a 5 second span. The solution assumes that this use-case is not a significant worry for the site owner which was the case with the site we had fixed this for.