Rack-Attack: Array of IP addresses

1.9k Views Asked by At

I'm trying to create an array of IP addresses so that when the application is ran Rack-Attack can identify from the set of IP addresses that are allowed to access the application. So what I have done is as followed:

  a = "127.0.0.1"
  Rack::Attack.blacklist('allow from localhost') do |req|
    p "#{'127.0.0.1' == req.ip} "
   a != req.ip 
  end

The above works, so localhost can access the application but I have tried the following below which seems to not work what so ever:

a = "127.0.0.1", "1.2.3.4"
  Rack::Attack.blacklist('allow from localhost') do |req|
    a.select{|x| x != req.ip}.join("")
  end

Can someone explain what the correct way would be to do this. You can see that I create an array. I want Rack::Attack to detect whether the IP address in the array has access or not.

3

There are 3 best solutions below

2
On BEST ANSWER

An efficient way to do this would be to use a Set, a container that's like an array but provides fast lookup on individual, unique elements.

So, rewritten with that in mind:

allowed = %w[ 127.0.0.1 1.2.3.4 ].to_set

Rack::Attack.blacklist('allow from localhost') do |req|
  !allowed.include?(req.ip)
end

In your original declaration:

a = "x", "y"

In this case a is assigned to the first thing in that list, "x", and the rest is ignored.

1
On

First off it would be nice if you were more explicit about creating an array and write

a = ["127.0.0.1", "1.2.3.4"]

but it's even better to use Set

allowed = Set.new['127.0.0.1', '1.2.3.4']

(also using single-quotes should save time as Ruby treats such string as literal, opposed to double-quotes)

To check if element is a member of an array you should use Array#include? so the code becomes

Rack::Attack.blacklist('allow from localhost') do |req|
  !a.include? req.ip
end
0
On

I know it's too late but I didn't like the Array#include? solution so I went ahead and added 2 new methods for safelist and blocklist each to have support for the same. Sharing it here as it will help other users too. It can be found in forked rack_attack branch.

Usage:

Safelisting:

# config/initializers/rack_attack.rb (for rails app)

ALLOWED_IPS = %w[127.0.0.1 ::1 5.6.7.8 123.456.789.0/24]

Rack::Attack.safelist_ips(ALLOWED_IPS)

Blocklisting:

# config/initializers/rack_attack.rb (for rails apps)

BLOCKED_IPS = %w[1.2.3.4 123.456.789.0/24]

Rack::Attack.blocklist_ips(BLOCKED_IPS)