Rack Attack Block List Doesn't work

1.3k Views Asked by At

I'm using the gem rack-attack and also gem geoip in rails 5. Have got everything setup well but for some reason, I can't get the blocklist to work to block a country code. I've setup a flash alert to make sure the correct country code is being passed, and it is ("CA"). "CA" is also on the blocklist but my app doesn't stop me from visiting the site as it should.

Where am I going wrong?

def get_ip
    @ip = request.ip
    @country = GeoIp.geolocation("#{@ip}", :precision => :country)
    country_code = @country[:country_code]


    Rack::Attack.safelist('allow from localhost and select countries') do |req|
      '127.0.0.1' || '::1' == req.ip || 'US' == req.country_code 

    end

   Rack::Attack.blocklist('block specific countries') do |req|
      "CA" == req.country_code

    end
  end
1

There are 1 best solutions below

2
SteveTurczyn On

EVERYTHING is on your safelist. See this block?

Rack::Attack.safelist('allow from localhost and select countries') do |req|
  '127.0.0.1' || '::1' == req.ip || 'US' == req.country_code 
  flash[:error] = "#{req.country_code}"
end

The last executable statement is the assignment of flash[:error] and that returns the string "#{req.country_code}" and any string is "truthy" so the block returns true.

Change the order of your statements so that the last statement will return the correct true/false value.

Rack::Attack.safelist('allow from localhost and select countries') do |req|
  flash[:error] = "#{req.country_code}"
  '127.0.0.1' || '::1' == req.ip || 'US' == req.country_code 
end

You have the same problem with your blocklist block... make sure the actual test is the last executed statement or you'll get always true.

EDIT

But I just noticed that you still have everything on your safelist... '127.0.0.1' is a string and strings are always truthy, so in...

'127.0.0.1' || ... 

The rest never gets evaluated because the string is true.

Maybe you wanted this...

Rack::Attack.safelist('allow from localhost and select countries') do |req|
  flash[:error] = "#{req.country_code}"
  '127.0.0.1' == req.ip || '::1' == req.ip || 'US' == req.country_code 
end