PlugAttack behaviour (plug_attack v0.4.3)
A plug building toolkit for blocking and throttling abusive requests.
PlugAttack is a set of macros that can be used to build a plug to protect your web app from bad clients. It allows safelisting, blocklisting and throttling based on arbitrary properties of the request.
The throttling state is stored in a configurable storage.
By default an implementation backed by :ets
tables is offered.
Example
defmodule MyApp.PlugAttack do
import Plug.Conn
use PlugAttack
# For more rules examples see PlugAttack.rule/2 macro documentation.
rule "allow local", conn do
allow conn.remote_ip == {127, 0, 0, 1}
end
# It's possible to customize what happens when conn is let through
def allow_action(conn, _data, _opts), do: conn
# Or when it's blocked
def block_action(conn, _data, _opts) do
conn
|> send_resp(:forbidden, "Forbidden\n")
|> halt
end
end
Link to this section Summary
Callbacks
Action performed when the request is allowed.
Action performed when the request is blocked.
Functions
Defines a rule.
Link to this section Types
rule()
Specs
The rule return value.
Link to this section Callbacks
allow_action(conn, term, term)
Specs
allow_action(conn :: Plug.Conn.t(), term(), term()) :: Plug.Conn.t()
Action performed when the request is allowed.
block_action(conn, term, term)
Specs
block_action(conn :: Plug.Conn.t(), term(), term()) :: Plug.Conn.t()
Action performed when the request is blocked.
Link to this section Functions
Defines a rule.
A rule is an expression that returns either {:allow, data}
, {:block, data}
,
or nil
. If an allow or block tuple is returned we say the rule matched,
otherwise the rule didn't match and further rules will be evaluated.
If a rule matched the corresponding allow_action/3
or block_action/3
function on the defining module will be called passing the conn
,
the data
value from the allow or block tuple and opts
as returned by the
init/1
plug callback. If none rule matched, neither allow_action/3
nor
block_action/3
will be called.
Both actions should behave similarly to plugs, returning the modified
conn
argument. The default implementation of allow_action/3
will
return the conn unmodified. The default implementation of block_action/3
will respond with status 403 Forbidden, the body "Forbidden\n"
and halt
the plug pipeline.
Various predefined rules are defined in the PlugAttack.Rule
module.
This module is automatically imported in the rule's body.
Examples
rule "allow local", conn do
allow conn.remote_ip == {127, 0, 0, 1}
end
rule "block 1.2.3.4", conn do
block conn.remote_ip == {1, 2, 3, 4}
end
rule "throttle per ip", conn do
# throttle to 5 requests per second
throttle conn.remote_ip,
period: 1_000, limit: 5,
storage: {PlugAttack.Storage.Ets, MyApp.PlugAttack.Storage}
end
rule "throttle login requests", conn do
if conn.method == "POST" and conn.path_info == ["login"] do
throttle conn.params["email"],
period: 60_000, limit: 10,
storage: {PlugAttack.Storage.Ets, MyApp.PlugAttack.Storage}
end
end