When you’re running community-driven website sooner or later you will have to fight back spammers. There can be different kind of spammers, but the main question here is - how do we stop them from flooding your precious site?
Few days ago I noticed huge spike in users registration count, apparently some ‘seo’ agency (quote indented) decided that website I’m running is a great place for new backlinks directory ;-).
I’m running devise with obligatory email confirmation, so that’s the first gate you have to pass. Let’s say you don’t have to confirm your account, what are the other options here? Obviously captcha comes to mind. You can go and try good (?) old reCAPTCHA, but personally I’m not a big fan of it. You can get some great results with something similar to Negative Captcha that is 100% transparent to the user.
If that won’t help I recommend using some heavy artillery - rack-attack. It’s a rack middleware that can be a great help in those situations. Let’s go over few common cases here:
- spam is coming from few IP addresses, maybe a IP range or something, it’s should be quite easy to block with this formula (first see usage notes):
Rack::Attack.blacklist('block spammers') do |req| ["126.96.36.199", "188.8.131.52", "and-so-on"].include?(req.ip) end
- you can’t filter traffic based on IP, but spammers are hitting your sign up page pretty hard - let’s blacklist too many sign up attempts
Rack::Attack.blacklist('allow2ban signup attempts') do |req| # After 5 requests in 6 hours, block all requests from that IP for 24 hours Rack::Attack::Allow2Ban.filter(req.ip, maxretry: 5, findtime: 6.hours, bantime: 24.hours) do req.post? && req.path =~ /sign_up/ # POST request pointed to your sign_up url end end
- still not good? Try limiting requests per seconds - just be sure to set this accordingly to your app (traffic you’re getting, amount of ajax requests etc.)
# Throttle requests to 5 requests per second per ip Rack::Attack.throttle("throttle req per ip", limit: 5, period: 1.second) do |req| req.ip end
Good luck and may the Force be with you ;-).