Rails
rack-attack

rails rack-attack gemで同一IPからの過剰なアクセスを制限する

概要

  • 無作法なbotなどによる過剰なリクエストを防止する
  • 方法は、rack-attack gemをインストールしてthrottleを設定すればOK
  • もし、development環境で効果を確認するにはrails dev:cacheをする

環境

  • rails: 5.1.4
  • rack-attack: 5.0.1

手順

gemインストール

Gemfileに下記を追加する

# for security
gem 'rack-attack'

なお、もしproductionだけにしたい場合は、下記の通り。

group :production do
  gem 'rack-attack'
end

bundle install実施

bundle install

これでインストール完了

設定

起動時に読み込む

  • developmentとproduction両方で読み込む場合
config/application.rb
module YourApp
  class Application < Rails::Application
    省略
    # security
    config.middleware.use Rack::Attack
  end
end
  • productionだけ読み込む場合
config/environments/production.rb
Rails.application.configure do
  config.middleware.use Rack::Attack
end

rack-attackの設定ファイル

config/initializers/rack-attack.rbを作成し、編集します。今回の目的に合致した例がrack-attack gem公式Example Configurationにありますので、部分抜粋することで実装します。

config/initializers/rack-attack.rb
class Rack::Attack
  throttle('req/ip', :limit => 300, :period => 5.minutes) do |req|
    req.ip # unless req.path.start_with?('/assets')
  end
end

上記の設定は、同一IPから5分間あたりに300回のリクエストがあった場合、そのIPからのアクセスを制限するという設定です。
各自の要望に合わせて、適宜、数値を変更してください。

確認

productionにdeployすれば動作確認できるのですが、それだと不安なのでdevelopment環境で動作を確認できるようにします。

こちらの記事を参考に下記のコマンドで設定します。

rails dev:cache

上記コマンドを入力することで、tmp/caching-dev.txtが作成されます。このファイルが存在するとconfig.action_controller.perform_caching = trueになりキャッシュが有効になり、リクエスト元のipが記録されrack-attackが機能するようになります。

config/environments/development.rb
  # Enable/disable caching. By default caching is disabled.
  if Rails.root.join('tmp/caching-dev.txt').exist? # ここでcaching-dev.txtの有無を判定する
    config.action_controller.perform_caching = true # これがキャッシュを有効にする

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end

なお、終了するときは、再度rails dev:cacheを実行してください。

動作テスト

development環境でrailsアプリを起動します。任意のページを表示させ、再読込(command+rとか)を300回(上記rack-attack.rbファイル参照)します。そうすると下記の表示に変わります。
これで、動作している事が確認できました。

https://gyazo.com/35ecc64272302b827b6547f33cc1fd24