Rack-Attack: Array of IP addresses
Asked Answered
E

4

4

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.

Embarkation answered 28/5, 2014 at 14:56 Comment(0)
F
2

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.

Foreleg answered 28/5, 2014 at 15:18 Comment(2)
You mentioning to_set triggered one of the key points the guy mentioned in the rails conf 2014 video: youtube.com/… but he does BANNED_IPS = Set.new['1.2.3.4', '5.6.7.8'] But thank youEmbarkation
Set.new([...]) and [...].to_set are two ways to get the same result.Foreleg
A
2

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
Apollonian answered 28/5, 2014 at 15:13 Comment(1)
Prior to your answer I tried this momentarily ago. I was following github.com/kickstarter/rack-attack#blacklists. However this only specifies one particular IP address. I want to specify an array of IP address's. Thank you for acknowledging the question.Embarkation
F
2

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.

Foreleg answered 28/5, 2014 at 15:18 Comment(2)
You mentioning to_set triggered one of the key points the guy mentioned in the rails conf 2014 video: youtube.com/… but he does BANNED_IPS = Set.new['1.2.3.4', '5.6.7.8'] But thank youEmbarkation
Set.new([...]) and [...].to_set are two ways to get the same result.Foreleg
C
1

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)
Conception answered 14/6, 2019 at 7:21 Comment(0)
M
0

This is what worked for me:

**# .env**
BLOCKED_IPS = 1.2.3.4, 123.456.789.0/24`


** # config/initializers/rack_attack.rb**

  bad_ips = ENV['BLOCKED_IPS'].split(',') # Pulled from a external API on app boot.
  Rack::Attack.blocklist "Block IPs from Environment Variable" do |req|
    bad_ips.include?(req.ip)
  end

See: https://wafris.org/guides/ultimate-guide-to-rack-attack

Marylou answered 7/6 at 15:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.