Entschuldigung für die Verzögerung, um zu Ihnen zurück zu kommen; Es dauerte eine Weile, bis ich meinen alten Code dazu ausgraben konnte.
Wie oben in den Kommentaren diskutiert, hier ist eine Lösung, die ein blacklist
, mit einem mit findtime
# config/initilizers/rack-attack.rb
class Rack::Attack
(1..6).each do |level|
blocklist("allow2ban login scrapers - level #{level}") do |req|
Allow2Ban.filter(
req.ip,
maxretry: (20 * level),
findtime: (8**level).seconds,
bantime: (8**level).seconds
) do
req.path == '/users/sign_in' && req.post?
end
end
end
end
Möglicherweise möchten Sie diese Zahlen zwicken, wie für die jeweilige Anwendung gewünscht; Die obigen Zahlen sind nur das, was ich als "vernünftig" für meine spezielle Anwendung empfand - sie stammen nicht aus irgendeinem offiziellen Standard.
Ein Problem mit den oben, dass die Verwendung bei der Entwicklung/Prüfung (zum Beispiel Ihre rspec
Testsuite), um die Anwendung können Sie leicht schlagen die oben genannten Grenzen und drosseln versehentlich selbst.
safelist('allow from localhost') do |req|
'127.0.0.1' == req.ip || '::1' == req.ip
end
Die häufigste Brute-Force-Login-Angriff ist ein Brute-Force-Angriff, bei dem ein Angreifer einfach eine große Anzahl von E-Mail versucht und Passwörtern, um zu sehen, wenn: Dies kann durch Hinzufügen des folgenden Config Initialisierungsstab vermieden werden alle Anmeldeinformationen übereinstimmen.
Sie sollten dies in der Anwendung durch die Verwendung eines Konto LOCK nach ein paar fehlgeschlagenen Anmeldeversuche mildern. (Wenn Sie z. B. devise
verwenden, können Sie eine integrierte verwenden.)
Diese Kontosperrmethode öffnet jedoch einen neuen Angriffsvektor: Ein Angreifer kann das System mit Anmeldeversuchen spammen, Verwenden Sie gültige E-Mails und falsche Passwörter, um alle Konten kontinuierlich neu zu sperren!
Diese Konfiguration hilft, diesen Angriffsvektor zu mindern, indem exponentiell die Anzahl der Anmeldeversuche von einer bestimmten IP begrenzt.
Ich habe auch das folgende "Catch-all" -Anforderung Gas:
throttle('req/ip', limit: 300, period: 5.minutes, &:ip)
Dies ist vor böswilligen/schlecht konfigurierten Schabern zu drosseln; um zu verhindern, dass sie die gesamte CPU des App-Servers in Beschlag nehmen.
Hinweis: Wenn Sie Assets über das Rack bereitstellen, werden diese Anfragen möglicherweise von Rack-Attacken gezählt und diese Drosselung kann zu schnell aktiviert werden. Wenn dies der Fall ist, aktivieren Sie die Bedingung, um sie vom Tracking auszuschließen.
Ich schrieb auch einen Integrationstest, um sicherzustellen, dass meine Rack::Attack
Konfiguration seine Arbeit tat. Es gab ein paar Probleme mit diesen Testarbeiten bei der Herstellung, also werde ich die Code + Kommentare sprechen für sich lassen:
class Rack::AttackTest < ActionDispatch::IntegrationTest
setup do
# Prevent subtle timing issues (==> intermittant test failures)
# when the HTTP requests span across multiple seconds
# by FREEZING TIME(!!) for the duration of the test
travel_to(Time.now)
@removed_safelist = Rack::Attack.safelists.delete('allow from localhost')
# Clear the Rack::Attack cache, to prevent test failure when
# running multiple times in quick succession.
#
# First, un-ban localhost, in case it is already banned after a previous test:
(1..6).each do |level|
Rack::Attack::Allow2Ban.reset('127.0.0.1', findtime: (8**level).seconds)
end
# Then, clear the 300-request rate limiter cache:
Rack::Attack.cache.delete("#{Time.now.to_i/5.minutes}:req/ip:127.0.0.1")
end
teardown do
travel_back # Un-freeze time
Rack::Attack.safelists['allow from localhost'] = @removed_safelist
end
test 'should block access on 20th successive /users/sign_in attempt' do
19.times do |i|
post user_session_url
assert_response :success, "was not even allowed to TRY to login on attempt number #{i + 1}"
end
# For DOS protection: Don't even let the user TRY to login; they're going way too fast.
# Rack::Attack returns 403 for blocklists by default, but this can be reconfigured:
# https://github.com/kickstarter/rack-attack/blob/master/README.md#responses
post user_session_url
assert_response :forbidden, 'login access should be blocked upon 20 successive attempts'
end
end
'Rack-:: Attack' normalerweise für * Drosselung großvolumige Anfragen * verwendet wird; Ich würde Regeln wie "3 fehlgeschlagene Versuche = 4 Sekunden Verzögerung" für viel zu streng halten. Lesen Sie die [Beispielkonfigurationen] (https://github.com/kickstarter/rack-attack/wiki/Example-Configuration). Ich glaube, was Sie hier wirklich erreichen wollen, wäre besser mit einem [exponentiellen Backoff] (https://github.com/kickstarter/rack-attack/wiki/Advanced-Configuration#exponential-backoff). –
Hey @ TomLord, vielen Dank für Ihr Feedback. Ich habe das gleiche Gefühl, dass das zu streng ist. Wie auch immer, ich habe die Beispielkonfigurationen gelesen, aber dieser exponentielle Backoff hinterlässt mich mit derselben Frage. In diesem Fall haben wir immer noch eine Drosselung über eine Ressource (das Login), aber das System würde insbesondere diejenigen, die versagen, nicht bestrafen, was, wie ich verstehe, die Absicht der Technik ist, die im Handbuch beschrieben wird. – IoChaos
Sie könnten 'blacklist' anstelle von' throttle' verwenden, mit fast dem gleichen Code wie in diesem Beispiel ... Ich habe genau diese Technik in einer Produktionsanwendung verwendet (einschließlich Tests, um sicherzustellen, dass es funktioniert). Wenn es hilft, könnte ich diesen Code ausgraben und unten einfügen? –