Replace `MastodonAPIController.account_register/2` rate limiter
This commit is contained in:
parent
f26013cf2e
commit
ad04d12de6
|
@ -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.
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue