Ruby on rails with nginx ddos protection
Asked Answered
N

2

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?

Neuropsychiatry answered 26/5, 2014 at 11:23 Comment(1)
There are several useful nginx directives for preventing HTTP flooding, see this question: #12299041 If the same IP floods you over and over it can be banned at the firewall level.Fredenburg
D
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.

Dichotomous answered 26/5, 2014 at 13:9 Comment(2)
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'Neuropsychiatry
That's even better solution, but requires some bash knowledge. Rack::Attack is for the rest of us ;)Dichotomous
M
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
Meddlesome answered 18/9, 2019 at 7:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.