Rails using kickstarter rack-attack IP blacklisting with Cloudflare

1.3k Views Asked by At

Rails app, using Kickstarter's rack-attack

Within my config/rack-attack.rb file, I have:

class Rack::Attack
  Rack::Attack.blacklist ('block ip') do |req|
    # Request are blocked if the return value is truthy
    '68.888.23.22' == req.ip
    # req.ip if IPCat.datacenter?(req.ip)
  end
end

This worked fine until I started using CloudFlare. The req.ip is now a Cloudflare IP vs that actual end user's IP

I had a similar issue when trying to save the user's IP to my server logs (was saving the Cloudflare IPs). In order to fix this, I added the following to my application controller:

module ActionDispatch
  class Request < Rack::Request
    alias :remote_ip_orig :remote_ip
    def remote_ip
      @remote_ip ||= (@env['HTTP_CF_CONNECTING_IP'] || remote_ip_orig)
    end
  end
end

Is there a similar process in order to use the HTTP_CF_CONNECTING_IP as the req.ip within rack-attack?

2

There are 2 best solutions below

0
On

Try to add:

class Rack::Attack::Request < ::Rack::Request
  def cf_ip
    @env['HTTP_CF_CONNECTING_IP'] ? @env['HTTP_CF_CONNECTING_IP'] : ip
  end
end

Then you can use:

throttle('req/ip', :limit => 300, :period => 5.minutes) do |req|
  req.cf_ip
end
0
On

If you want to solve the problem on both ActionPack and the Rack::Attack::Request you can do this:

module ActionPack
  module Cloudflare
    module Request

      def remote_ip
        remote_ip_cloudflare || super
      end

      private

      def remote_ip_cloudflare
        @env['HTTP_CF_CONNECTING_IP']
      end

    end
  end
end

ActionDispatch::Request.class_eval do
  prepend ActionPack::Cloudflare::Request
end

Rack::Attack::Request.class_eval do
  prepend ActionPack::Cloudflare::Request
end

I hope it helps.