はじめに
この記事では、RailsアプリケーションにおけるDoS攻撃防止策として、Rack::Attack
の設定方法についてステップバイステップで解説します。Rack::Attack
は、不正なアクセスや不要なトラフィックを制限するためのミドルウェアであり、アプリケーションを保護する上で非常に有効です。
ステップ1: Gem の追加
まず、RailsプロジェクトのGemfile
に以下の行を追加し、rack-attack
gemをプロジェクトにインクルードします。
gem 'rack-attack'
追加後、ターミナルで以下のコマンドを実行して、gemをインストールします。
bundle
ステップ2: 初期化ファイルの設定
rack-attack
の設定を管理するために、config/initializers/rack_attack.rb
ファイルを作成します。ファイルには、特定のリクエストを制限するための設定を記述します。以下はその一例です。
class Rack::Attack
# ユーザーごとの予約リクエストを制限
throttle('request by user', limit: 150, period: 1.hour) do |req|
if req.path.start_with?('/reservations') && req.post? # postのみに適用
warden_info = req.env['warden'].user(:customer)
warden_info&.id.to_s
end
end
throttle('logins/email', limit: 5, period: 20.seconds) do |req|
if req.path == '/login' && req.post?
req.params['email'].presence
end
end
# イベントを購読してログに記録
ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, req|
Rails.logger.info "Rack::Attack: #{req.env['rack.attack.match_type']} from #{req.ip} blocked."
end
end
ステップ3: Middleware として追加
次に、Rack::Attack
をRailsアプリケーションのミドルウェアスタックに追加する必要があります。config/application.rb
ファイルを開き、以下の行を追加します。
config.middleware.use Rack::Attack
ステップ4: キャッシュストアの設定
Rack::Attack
はリクエストの頻度を追跡するためにキャッシュストアを利用します。Railsでは標準でいくつかのキャッシュストアが用意されていますが、本例ではRedisを使用します。Redisの設定は以下の通りです。
※Redisはインメモリデータストアであり、データベース、キャッシュ、メッセージブローカーとして広く使われています。Railsアプリケーションでキャッシュシステムとして利用されることが多いですが、他にもMemcachedなどがよく使われます。
Rack::Attack.cache.store = ActiveSupport::Cache::RedisCacheStore.new(url: ENV['REDIS_URL'])
開発環境で使用する場合は以下の通りです。
config.cache_store = :redis_cache_store, { url: 'redis://localhost:6379/1' }
この設定を行う前に、Redisサーバーが起動していることを確認してください。
ステップ5: ログの設定
Rack::Attack
の動作を監視するために、ログ設定を追加することが推奨されます。以下の設定をconfig/initializers/rack_attack.rb
に追加することで、攻撃を検出した際にログを出力できます。
ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, req|
Rails.logger.info "Rack::Attack: #{req.env['rack.attack.match_type']} #{req.path}"
end
以上の設定により、Rack::Attack
を利用してRailsアプリケーションのセキュリティを向上させることができます。次のステップでは、これらの設定をテストし、適切に動作するかを確認する方法について説明します。
補足: エラーハンドリング
Rack-Attackが設定どおりにブロックしない場合は、以下のことを試してください。
1. Rails consoleでRedisの存在とキャッシュの設定を確認
以下のようにコンソールから現在設定されているキャッシュストアを確認できます
rails console
コンソールで以下のコマンドを実行してください:
puts Rails.configuration.cache_store
また、以下のコマンドを実行します
(base) Kengo% redis-cli
zsh: command not found: redis-cli
(base) Kengo%
以下のようになる場合、現在のRailsアプリケーションで設定されているキャッシュストアはnull_store
です。これは実際には何もキャッシュしない設定で、キャッシュストアとして機能しないため、Rack::Attack
のような機能でリクエストを追跡して制限を行う場合には適していません。
[1] pry(main)> puts Rails.configuration.cache_store
null_store
=> nil
Rack::Attackを有効に使用するためには、有効なキャッシュストア(例えばRedisやMemcached)を設定する必要があります。Redisをキャッシュストアとして設定する基本的な手順は以下の通りです。