Replace MastodonAPIController.account_register/2 rate limiter

This commit is contained in:
Egor Kislitsyn 2019-06-11 16:06:03 +07:00
parent f26013cf2e
commit ad04d12de6
7 changed files with 7 additions and 125 deletions

View file

@ -247,8 +247,6 @@
skip_thread_containment: false, skip_thread_containment: false,
limit_unauthenticated_to_local_content: true limit_unauthenticated_to_local_content: true
config :pleroma, :app_account_creation, enabled: true, max_requests: 25, interval: 1800
config :pleroma, :markup, config :pleroma, :markup,
# XXX - unfortunately, inline images must be enabled by default right now, because # XXX - unfortunately, inline images must be enabled by default right now, because
# of custom emoji. Issue #275 discusses defanging that somehow. # of custom emoji. Issue #275 discusses defanging that somehow.
@ -503,7 +501,9 @@
config :http_signatures, config :http_signatures,
adapter: Pleroma.Signature adapter: Pleroma.Signature
config :pleroma, :rate_limit, search: [{1000, 10}, {1000, 30}] config :pleroma, :rate_limit,
search: [{1000, 10}, {1000, 30}],
app_account_creation: {1_800_000, 25}
# Import environment specific config. This must remain at the bottom # Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above. # of this file so it overrides the configuration defined above.

View file

@ -59,7 +59,7 @@
total_user_limit: 3, total_user_limit: 3,
enabled: false enabled: false
config :pleroma, :app_account_creation, max_requests: 5 config :pleroma, :rate_limit, app_account_creation: {1000, 5}
config :pleroma, :http_security, report_uri: "https://endpoint.com" config :pleroma, :http_security, report_uri: "https://endpoint.com"

View file

@ -114,12 +114,6 @@ config :pleroma, Pleroma.Emails.Mailer,
* `skip_thread_containment`: Skip filter out broken threads. The default is `false`. * `skip_thread_containment`: Skip filter out broken threads. The default is `false`.
* `limit_unauthenticated_to_local_content`: Limit unauthenticated users to search for local statutes and users only. The default is `true`. * `limit_unauthenticated_to_local_content`: Limit unauthenticated users to search for local statutes and users only. The default is `true`.
## :app_account_creation
REST API for creating an account settings
* `enabled`: Enable/disable registration
* `max_requests`: Number of requests allowed for creating accounts
* `interval`: Interval for restricting requests for one ip (seconds)
## :logger ## :logger
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog, and `Quack.Logger` to log to Slack * `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog, and `Quack.Logger` to log to Slack
@ -568,7 +562,7 @@ config :ueberauth, Ueberauth,
providers: [ providers: [
microsoft: {Ueberauth.Strategy.Microsoft, [callback_params: []]} microsoft: {Ueberauth.Strategy.Microsoft, [callback_params: []]}
] ]
# Keycloak # Keycloak
# Note: make sure to add `keycloak:ueberauth_keycloak_strategy` entry to `OAUTH_CONSUMER_STRATEGIES` environment variable # Note: make sure to add `keycloak:ueberauth_keycloak_strategy` entry to `OAUTH_CONSUMER_STRATEGIES` environment variable
keycloak_url = "https://publicly-reachable-keycloak-instance.org:8080" keycloak_url = "https://publicly-reachable-keycloak-instance.org:8080"

View file

@ -1,36 +0,0 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Plugs.RateLimitPlug do
import Phoenix.Controller, only: [json: 2]
import Plug.Conn
def init(opts), do: opts
def call(conn, opts) do
enabled? = Pleroma.Config.get([:app_account_creation, :enabled])
case check_rate(conn, Map.put(opts, :enabled, enabled?)) do
{:ok, _count} -> conn
{:error, _count} -> render_error(conn)
%Plug.Conn{} = conn -> conn
end
end
defp check_rate(conn, %{enabled: true} = opts) do
max_requests = opts[:max_requests]
bucket_name = conn.remote_ip |> Tuple.to_list() |> Enum.join(".")
ExRated.check_rate(bucket_name, opts[:interval] * 1000, max_requests)
end
defp check_rate(conn, _), do: conn
defp render_error(conn) do
conn
|> put_status(:forbidden)
|> json(%{error: "Rate limit exceeded."})
|> halt()
end
end

View file

@ -46,15 +46,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
require Logger require Logger
plug( plug(Pleroma.Plugs.RateLimiter, :app_account_creation when action == :account_register)
Pleroma.Plugs.RateLimitPlug,
%{
max_requests: Config.get([:app_account_creation, :max_requests]),
interval: Config.get([:app_account_creation, :interval])
}
when action in [:account_register]
)
plug(Pleroma.Plugs.RateLimiter, :search when action in [:search, :search2, :account_search]) plug(Pleroma.Plugs.RateLimiter, :search when action in [:search, :search2, :account_search])
@local_mastodon_name "Mastodon-Local" @local_mastodon_name "Mastodon-Local"

View file

@ -1,50 +0,0 @@
defmodule Pleroma.Plugs.RateLimitPlugTest do
use ExUnit.Case, async: true
use Plug.Test
alias Pleroma.Plugs.RateLimitPlug
@opts RateLimitPlug.init(%{max_requests: 5, interval: 1})
setup do
enabled = Pleroma.Config.get([:app_account_creation, :enabled])
Pleroma.Config.put([:app_account_creation, :enabled], true)
on_exit(fn ->
Pleroma.Config.put([:app_account_creation, :enabled], enabled)
end)
:ok
end
test "it restricts by opts" do
conn = conn(:get, "/")
bucket_name = conn.remote_ip |> Tuple.to_list() |> Enum.join(".")
ms = 1000
conn = RateLimitPlug.call(conn, @opts)
{1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
conn = RateLimitPlug.call(conn, @opts)
{2, 3, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
conn = RateLimitPlug.call(conn, @opts)
{3, 2, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
conn = RateLimitPlug.call(conn, @opts)
{4, 1, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
conn = RateLimitPlug.call(conn, @opts)
{5, 0, to_reset, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
conn = RateLimitPlug.call(conn, @opts)
assert conn.status == 403
assert conn.halted
assert conn.resp_body == "{\"error\":\"Rate limit exceeded.\"}"
Process.sleep(to_reset)
conn = conn(:get, "/")
conn = RateLimitPlug.call(conn, @opts)
{1, 4, _, _, _} = ExRated.inspect_bucket(bucket_name, ms, 5)
refute conn.status == 403
refute conn.halted
refute conn.resp_body
end
end

View file

@ -3501,24 +3501,6 @@ test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{c
end end
describe "create account by app" do describe "create account by app" do
setup do
enabled = Pleroma.Config.get([:app_account_creation, :enabled])
max_requests = Pleroma.Config.get([:app_account_creation, :max_requests])
interval = Pleroma.Config.get([:app_account_creation, :interval])
Pleroma.Config.put([:app_account_creation, :enabled], true)
Pleroma.Config.put([:app_account_creation, :max_requests], 5)
Pleroma.Config.put([:app_account_creation, :interval], 1)
on_exit(fn ->
Pleroma.Config.put([:app_account_creation, :enabled], enabled)
Pleroma.Config.put([:app_account_creation, :max_requests], max_requests)
Pleroma.Config.put([:app_account_creation, :interval], interval)
end)
:ok
end
test "Account registration via Application", %{conn: conn} do test "Account registration via Application", %{conn: conn} do
conn = conn =
conn conn
@ -3621,7 +3603,7 @@ test "rate limit", %{conn: conn} do
agreement: true agreement: true
}) })
assert json_response(conn, 403) == %{"error" => "Rate limit exceeded."} assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
end end
end end