How can you block or filter IP addresses on Heroku?

23

6

Is there a way to implement IP filtering or IP access rules much like I would with nginx/apache to restrict or block certain IPs on Heroku?

Note: I know this can be done from within my application (Rails 3.2) very easily but I don't think this is the most efficient use of my resources on Heroku. Also, a Rack based solution would be better than implementing the filtering in Rails.

Matt Smith

Posted 2012-08-27T04:34:32.257

Reputation: 2 526

Answers

7

I added 'rack-block' as Rack middleware. In config/initializers, add a new file:

YourApp::Application.configure do

  config.middleware.insert_before(Rack::Lock, Rack::Block) do  
    # Add your rules with the rack-block syntax in here
  end

end

Works like a charm.

Nate Berkopec

Posted 2012-08-27T04:34:32.257

Reputation: 173

2Thanks, this is exactly what I was looking for. I'm kinda concerned with my googling skills now. – Matt Smith – 2012-09-05T23:13:21.737

4Is there a way to block centain addresses before the request hit the dyno? – Michał Szajbe – 2013-09-13T11:29:54.213

How can I block all IP addresses except for one IP I want to allow? To me it seems with rack-block I have to list ALL IP addresses I want to block :( – morgler – 2014-01-30T09:16:36.360

1

@morgler: check out my answer below. rack-attack has a whitelist feature - https://github.com/kickstarter/rack-attack

– Phil – 2014-10-10T17:48:55.880

Is it possible to block IPs at a 'server' level, so that we don't have to muck around with our app? – PKHunter – 2017-09-06T22:32:58.087

16

You should check out rack-attack. Looks like it does the same as rack-block, but is much more widely used and updated frequently. To block a specific IP you can do this:

# Block requests from 1.2.3.4
Rack::Attack.blacklist('block 1.2.3.4') do |req|
  # Requests are blocked if the return value is truthy
  '1.2.3.4' == req.ip
end

Phil

Posted 2012-08-27T04:34:32.257

Reputation: 1 551

Can I block an IP range? i.e 1.2.3.*? – Stefanos.Ioannou – 2016-08-31T13:34:15.520

1@Stefanos.Ioannou to block the value you just need to make sure the block you pass to Rack::Attack.blacklist returns true. You could do something like this:

(0..255).map{ |val| '1.2.3.' + val.to_s }.include?(req.ip) – Phil – 2016-09-05T22:17:55.510

2@Phil I'm being pedantic about a contrived example, but... ;) You'd probably be better off with starts_with?('1.2.3') there - building an array of 256 strings, then checking if the ip is amongst those might not be massive computationally, but possibly not something you want to do on every request if not necessary. – Sam Peacey – 2017-04-15T06:07:15.570