Rails 试图通过机架攻击来限制我的 API。不确定它是否有效?

Jwa*_*622 5 api ruby-on-rails

这是我的回购

我刚刚添加了机架攻击宝石。

gem 'rack-attack'
Run Code Online (Sandbox Code Playgroud)

这是我的 app/initializers/rack-attack.rb 文件:

class Rack::Attack

  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new

  whitelist('allow-localhost') do |req|
    '127.0.0.1' == req.ip || '::1' == req.ip
  end

  throttle('req/ip', limit: 10, period: 10) do |req|
    req.ip
  end

  self.throttled_response = ->(env) {
    retry_after = (env['rack.attack.match_data'] || {})[:period]
    [
      429,
      {'Content-Type' => 'application/json', 'Retry-After' => retry_after.to_s},
      [{error: "Throttle limit reached. Retry later."}.to_json]
    ]
  }
end
Run Code Online (Sandbox Code Playgroud)

这是我的 application.rb 文件:

module ApiCodeship
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.

    # Only loads a smaller set of middleware suitable for API only apps.
    # Middleware like session, flash, cookies can be added back manually.
    # Skip views, helpers and assets when generating a new resource.
    config.api_only = true
    config.middleware.use Rack::Attack
  end
end
Run Code Online (Sandbox Code Playgroud)

当我访问http://localhost:3000/rental_units 时,这是我在控制台中的日志:

Started GET "/rental_units" for ::1 at 2016-03-03 23:01:32 -0500
  ActiveRecord::SchemaMigration Load (0.4ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by RentalUnitsController#index as HTML
  RentalUnit Load (0.5ms)  SELECT "rental_units".* FROM "rental_units"
[active_model_serializers] Dalli::Server#connect localhost:11211
[active_model_serializers]   User Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
[active_model_serializers]   CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
[active_model_serializers]   CACHE (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
[active_model_serializers]   User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModel::Serializer::Adapter::JsonApi (44.37ms)
Completed 200 OK in 62ms (Views: 57.8ms | ActiveRecord: 2.7ms)
Run Code Online (Sandbox Code Playgroud)

我怎么知道我正在正确节流?

hve*_*les 5

我最近一直在我的应用程序中实施机架攻击。我发现了一些关于测试 Rack::Attack 的非常有用的博客文章。

基本上,以下建议您安装 gem 'rack-test'

然后include Rack::Test::Methods,您可以在 rspec 文件的顶部,这将使您能够编写测试,例如;

describe 'throttling urls' do
  include Rack::Test::Methods

  def app
    Rails.application
  end

  describe 'throttle excessive requests by IP address' do
  let(:limit) { 10 }

    context 'number of requests is lower than the limit' do
      it "does not chnage the request status" do
        limit.times do
          get '/show', {}, "REMOTE_ADDR" => "1.2.3.4"
          expect(last_response.status).to_not eq 429
        end
      end
    end

    context 'number of requests is higher than the limit' do
      it 'changes the request status to 429' do
        (limit * 2).times do |i|
          get '/show', {}, "REMOTE_ADDR" => "1.2.3.5"
          expect(last_response.status).to eq(429) if i > limit
        end
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我关注的博客是;

如果使用旧的 rspec 语法,这篇博文很棒

最近关于测试机架攻击的博客,但不太详细


mmi*_*ike 5

也许开发 Rails 服务器应该开始缓存。在文件development.rb中更改:

config.action_controller.perform_caching = false
Run Code Online (Sandbox Code Playgroud)

config.action_controller.perform_caching = true
Run Code Online (Sandbox Code Playgroud)

并重新启动服务器。在对您的限制路线发出 10 + 1 次请求后,您将收到预期的阻止/限制。