6

I have rails3 + nginx stack.

Several days ago it was ddos attack with lots of GET requests similar to:

GET /?aaa2=bbbbbbb&ccc=1234212
GET /?aaa1=bbbbbbb&ccc=4324233

First of all I added to application controller rule:

before_filter :ddos_check
def ddos_check
  params.each do |param|
    if (!param[1].nil? && (param[1].is_a?String) && !param[1].scan(/bbb/sim).blank?)
      redirect_to 'http://google.com/'
      return
    end
  end
end

It protects controllers from heavy DB calls.

Is it any gems or nginx modules that can filter ddos messages with specific rules?

Voldemar Duletskiy
  • 981
  • 1
  • 11
  • 30
  • 2
    There are several useful nginx directives for preventing HTTP flooding, see this question: http://stackoverflow.com/questions/12298541/config-of-nginx-to-filter-http-flood If the same IP floods you over and over it can be banned at the firewall level. – Arctodus May 26 '14 at 13:16

2 Answers2

22

You should rather consider using a middleware like Rack::Attack. As it's lower in app stack it will filter out malicious request earlier and faster than Rails.

Rack middleware for blocking & throttling abusive requests

Rack::Attack is a rack middleware to protect your web app from bad clients. It allows whitelisting, blacklisting, throttling, and tracking based on arbitrary properties of the request.

If you take a look at gem readme there are nice examples how to handle cases such as yours. However keep in mind that if attackers are at least a little smart, they will notice your endeavour and try to outsmart them. DDOS protection is usually cat and mouse game.

Mike Szyndel
  • 10,461
  • 10
  • 47
  • 63
  • 3
    solved by following commands: 'grep "msg.*=wow" /var/log/nginx/access.log | awk "{print $1}" | sort | uniq | wc -l > ddos.txt' and 'for IP in $(cat ddos.txt); do echo "Banning $IP"; iptables -A INPUT -s $IP/32 -d 0/0 -j DROP; done' – Voldemar Duletskiy May 27 '14 at 00:07
  • 5
    That's even better solution, but requires some bash knowledge. Rack::Attack is for the rest of us ;) – Mike Szyndel May 27 '14 at 09:22
0

We can use "rack-attack" gem to prevent wasting bandwidth. We can manually run the commands in the production rails console to ban IPs:

Rails.cache.write('block 1.2.3.4', true, expires_in: 5.days)

The rack initializer would then block this IP:

Rack::Attack.blacklist('block <ip>') do |req|
  # if variable `block <ip>` exists in cache store, then we'll block the request
  Rails.cache.fetch("block #{req.ip}").blank?
end
Rakesh
  • 793
  • 4
  • 22