|
|
|
@ -10,14 +10,7 @@ defmodule BlockScoutWeb.AccessHelpers do |
|
|
|
|
alias BlockScoutWeb.WebRouter.Helpers |
|
|
|
|
alias Plug.Conn |
|
|
|
|
|
|
|
|
|
defp get_restricted_key(%Phoenix.Socket{}) do |
|
|
|
|
nil |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp get_restricted_key(conn) do |
|
|
|
|
conn_with_params = Conn.fetch_query_params(conn) |
|
|
|
|
conn_with_params.query_params["key"] |
|
|
|
|
end |
|
|
|
|
alias RemoteIp |
|
|
|
|
|
|
|
|
|
def restricted_access?(address_hash, params) do |
|
|
|
|
restricted_list_var = Application.get_env(:block_scout_web, :restricted_list) |
|
|
|
@ -78,28 +71,80 @@ defmodule BlockScoutWeb.AccessHelpers do |
|
|
|
|
if Mix.env() == :test do |
|
|
|
|
:ok |
|
|
|
|
else |
|
|
|
|
global_api_rate_limit = Application.get_env(:block_scout_web, :global_api_rate_limit) |
|
|
|
|
api_rate_limit_by_key = Application.get_env(:block_scout_web, :api_rate_limit_by_key) |
|
|
|
|
static_api_key = Application.get_env(:block_scout_web, :static_api_key) |
|
|
|
|
|
|
|
|
|
if conn.query_params && Map.has_key?(conn.query_params, "apikey") && |
|
|
|
|
Map.get(conn.query_params, "apikey") == static_api_key do |
|
|
|
|
case Hammer.check_rate("api-#{static_api_key}", 1_000, api_rate_limit_by_key) do |
|
|
|
|
{:allow, _count} -> |
|
|
|
|
:ok |
|
|
|
|
|
|
|
|
|
{:deny, _limit} -> |
|
|
|
|
:rate_limit_reached |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
case Hammer.check_rate("api", 1_000, global_api_rate_limit) do |
|
|
|
|
{:allow, _count} -> |
|
|
|
|
:ok |
|
|
|
|
|
|
|
|
|
{:deny, _limit} -> |
|
|
|
|
:rate_limit_reached |
|
|
|
|
end |
|
|
|
|
global_api_rate_limit = Application.get_env(:block_scout_web, :api_rate_limit)[:global_limit] |
|
|
|
|
api_rate_limit_by_key = Application.get_env(:block_scout_web, :api_rate_limit)[:api_rate_limit_by_key] |
|
|
|
|
api_rate_limit_by_ip = Application.get_env(:block_scout_web, :api_rate_limit)[:limit_by_ip] |
|
|
|
|
static_api_key = Application.get_env(:block_scout_web, :api_rate_limit)[:static_api_key] |
|
|
|
|
|
|
|
|
|
remote_ip = conn.remote_ip |
|
|
|
|
remote_ip_from_headers = RemoteIp.from(conn.resp_headers) |
|
|
|
|
ip = remote_ip_from_headers || remote_ip |
|
|
|
|
ip_string = to_string(:inet_parse.ntoa(ip)) |
|
|
|
|
|
|
|
|
|
cond do |
|
|
|
|
conn.query_params && Map.has_key?(conn.query_params, "apikey") && |
|
|
|
|
Map.get(conn.query_params, "apikey") == static_api_key -> |
|
|
|
|
rate_limit_by_key(static_api_key, api_rate_limit_by_key) |
|
|
|
|
|
|
|
|
|
Enum.member?(api_rate_limit_whitelisted_ips(), ip_string) -> |
|
|
|
|
rate_limit_by_ip(ip_string, api_rate_limit_by_ip) |
|
|
|
|
|
|
|
|
|
true -> |
|
|
|
|
global_rate_limit(global_api_rate_limit) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp rate_limit_by_key(api_key, api_rate_limit_by_key) do |
|
|
|
|
case Hammer.check_rate("api-#{api_key}", 1_000, api_rate_limit_by_key) do |
|
|
|
|
{:allow, _count} -> |
|
|
|
|
:ok |
|
|
|
|
|
|
|
|
|
{:deny, _limit} -> |
|
|
|
|
:rate_limit_reached |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp rate_limit_by_ip(ip_string, api_rate_limit_by_ip) do |
|
|
|
|
case Hammer.check_rate("api-#{ip_string}", 1_000, api_rate_limit_by_ip) do |
|
|
|
|
{:allow, _count} -> |
|
|
|
|
:ok |
|
|
|
|
|
|
|
|
|
{:deny, _limit} -> |
|
|
|
|
:rate_limit_reached |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp global_rate_limit(global_api_rate_limit) do |
|
|
|
|
case Hammer.check_rate("api", 1_000, global_api_rate_limit) do |
|
|
|
|
{:allow, _count} -> |
|
|
|
|
:ok |
|
|
|
|
|
|
|
|
|
{:deny, _limit} -> |
|
|
|
|
:rate_limit_reached |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp get_restricted_key(%Phoenix.Socket{}) do |
|
|
|
|
nil |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp get_restricted_key(conn) do |
|
|
|
|
conn_with_params = Conn.fetch_query_params(conn) |
|
|
|
|
conn_with_params.query_params["key"] |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp api_rate_limit_whitelisted_ips do |
|
|
|
|
with api_rate_limit_object <- |
|
|
|
|
:block_scout_web |
|
|
|
|
|> Application.get_env(:api_rate_limit), |
|
|
|
|
{:ok, whitelisted_ips_string} <- |
|
|
|
|
api_rate_limit_object && |
|
|
|
|
api_rate_limit_object |
|
|
|
|
|> Keyword.fetch(:whitelisted_ips) do |
|
|
|
|
if whitelisted_ips_string, do: String.split(whitelisted_ips_string, ","), else: [] |
|
|
|
|
else |
|
|
|
|
_ -> [] |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|