77 lines
1.9 KiB
Elixir
77 lines
1.9 KiB
Elixir
defmodule Mobilizon.Web.Plugs.PlugAttack do
|
|
@moduledoc false
|
|
use PlugAttack
|
|
import Plug.Conn
|
|
|
|
@alg :sha512
|
|
|
|
rule "allow local", conn do
|
|
allow(conn.remote_ip == {127, 0, 0, 1})
|
|
end
|
|
|
|
# rule "throttle by ip", conn do
|
|
# throttle hash_ip(@alg, convert_ip(conn.remote_ip)),
|
|
# period: 60_000, limit: 5,
|
|
# storage: {PlugAttack.Storage.Ets, Mobilizon.Web.Plugs.PlugAttack.Storage}
|
|
# end
|
|
|
|
rule "fail2ban by ip", conn do
|
|
fail2ban(hash_ip(@alg, convert_ip(conn.remote_ip)),
|
|
period: 6_000,
|
|
limit: 5,
|
|
ban_for: 90_000,
|
|
storage: {PlugAttack.Storage.Ets, Mobilizon.Web.Plugs.PlugAttack.Storage}
|
|
)
|
|
end
|
|
|
|
def allow_action(conn, {:throttle, data}, opts) do
|
|
conn
|
|
|> add_throttling_headers(data)
|
|
|> allow_action(true, opts)
|
|
end
|
|
|
|
def allow_action(conn, _data, _opts) do
|
|
conn
|
|
end
|
|
|
|
def block_action(conn, {:throttle, data}, opts) do
|
|
conn
|
|
|> add_throttling_headers(data)
|
|
|> block_action(false, opts)
|
|
end
|
|
|
|
def block_action(conn, _data, _opts) do
|
|
conn
|
|
|> send_resp(:forbidden, "Forbidden\n")
|
|
# It's important to halt connection once we send a response early
|
|
|> halt
|
|
end
|
|
|
|
defp add_throttling_headers(conn, data) do
|
|
# The expires_at value is a unix time in milliseconds, we want to return one
|
|
# in seconds
|
|
reset = div(data[:expires_at], 1_000)
|
|
|
|
conn
|
|
|> put_resp_header("x-ratelimit-limit", to_string(data[:limit]))
|
|
|> put_resp_header("x-ratelimit-remaining", to_string(data[:remaining]))
|
|
|> put_resp_header("x-ratelimit-reset", to_string(reset))
|
|
end
|
|
|
|
defp hash_ip(alg, ip) do
|
|
ip_hash_secret =
|
|
:mobilizon
|
|
|> Application.get_env(Mobilizon.Web.Endpoint)
|
|
|> Keyword.get(:secret_key_base, "HASH_IP_SECRET")
|
|
|
|
:crypto.mac(:hmac, alg, ip_hash_secret, ip)
|
|
end
|
|
|
|
defp convert_ip(ip) do
|
|
ip
|
|
|> Tuple.to_list()
|
|
|> List.to_charlist()
|
|
|> IO.chardata_to_string()
|
|
end
|
|
end
|