Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions lib/rule.ex
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ defmodule PlugAttack.Rule do
Be careful not to use the same `key` for different rules that use the same
storage.

Passes `{:fail2ban, key}`, as the data to `block_action` calls when an
Passes `{:fail2ban, key, remaining_ban}`, as the data to `block_action` calls when an
abusive request is detected. Each misbehaving client is blocked after each
call and tracked for `:period` time. If more than `:limit` abusive requests
are detected within the `:period`, the client is banned for `:ban_for`.
Expand Down Expand Up @@ -129,15 +129,17 @@ defmodule PlugAttack.Rule do
ban_for = Keyword.fetch!(opts, :ban_for)
now = System.system_time(:millisecond)

if banned?(key, storage, now) do
{:block, {:fail2ban, :banned, key}}
else
track_fail2ban(key, storage, limit, period, ban_for, now)
case banned?(key, storage, now) do
{true, remaining_ban} -> {:block, {:fail2ban, :banned, key, remaining_ban}}
false -> track_fail2ban(key, storage, limit, period, ban_for, now)
end
end

defp banned?(key, {mod, opts}, now) do
mod.read(opts, {:fail2ban_banned, key}, now) == {:ok, true}
case mod.read(opts, {:fail2ban_banned, key}, now) do
{:ok, true, remaining_ban} -> {true, remaining_ban}
_ -> false
end
end

defp track_fail2ban(key, {mod, opts}, limit, period, ban_for, now) do
Expand Down
2 changes: 1 addition & 1 deletion lib/storage/ets.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ defmodule PlugAttack.Storage.Ets do
def read(name, key, now) do
case :ets.lookup(name, key) do
[{^key, value, expires_at}] when expires_at > now ->
{:ok, value}
{:ok, value, expires_at - now}

_ ->
:error
Expand Down
2 changes: 1 addition & 1 deletion test/rules_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule PlugAttack.RuleTest do
:timer.sleep(1)
assert {:allow, {:fail2ban, :counting, :key}} = fail2ban()
:timer.sleep(100)
assert {:block, {:fail2ban, :banned, :key}} = fail2ban()
assert {:block, {:fail2ban, :banned, :key, 99}} = fail2ban()
:timer.sleep(200)
assert {:allow, {:fail2ban, :counting, :key}} = fail2ban()
end
Expand Down
2 changes: 1 addition & 1 deletion test/storage/ets_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ defmodule PlugAttack.Storage.EtsTest do
test "read/write" do
assert :error = Ets.read(__MODULE__, :foo, now())
Ets.write(__MODULE__, :foo, true, expires_in(20))
assert {:ok, true} == Ets.read(__MODULE__, :foo, now())
assert {:ok, true, 20} == Ets.read(__MODULE__, :foo, now())
:timer.sleep(30)
assert :error = Ets.read(__MODULE__, :foo, now())
end
Expand Down