- Sign-up, login, the invitation flows and password recovery allow ten requests a minute per client address; the inboxes give each sending origin (the keyId's) a bucket of 300 that refills at 300 a minute, and answer 429 beyond it, which peers retry. - deploy.yml dumps the PrivaPub database to /var/backups before it stops the service (the last seven are kept), and after the swap checks that Swagger answers 404 and that the shared inbox answers junk with 400 and an unsigned activity with 401. - ActivityPubClient and PostBoost, never used, are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
40 lines
1.3 KiB
C#
40 lines
1.3 KiB
C#
using Microsoft.AspNetCore.RateLimiting;
|
|
|
|
using PrivaPub.Federation.Objects;
|
|
using PrivaPub.Federation.Signing;
|
|
|
|
using System.Threading.RateLimiting;
|
|
|
|
namespace PrivaPub.Infrastructure
|
|
{
|
|
public static class RateLimiting
|
|
{
|
|
public const string Accounts = "accounts";
|
|
public const string Inbox = "inbox";
|
|
|
|
public static IServiceCollection PrivaPubRateLimiting(this IServiceCollection service) =>
|
|
service.AddRateLimiter(options =>
|
|
{
|
|
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
|
options.AddPolicy(Accounts, context => RateLimitPartition.GetFixedWindowLimiter(
|
|
context.Connection.RemoteIpAddress?.ToString() ?? "unknown",
|
|
_ => new FixedWindowRateLimiterOptions { PermitLimit = 10, Window = TimeSpan.FromMinutes(1), QueueLimit = 0 }));
|
|
options.AddPolicy(Inbox, context => RateLimitPartition.GetTokenBucketLimiter(
|
|
SenderOrigin(context.Request) ?? "unsigned:" + context.Connection.RemoteIpAddress,
|
|
_ => new TokenBucketRateLimiterOptions
|
|
{
|
|
TokenLimit = 300,
|
|
TokensPerPeriod = 50,
|
|
ReplenishmentPeriod = TimeSpan.FromSeconds(10),
|
|
QueueLimit = 0
|
|
}));
|
|
});
|
|
|
|
static string SenderOrigin(HttpRequest request)
|
|
{
|
|
var signature = request.Headers["Signature"].ToString();
|
|
return string.IsNullOrEmpty(signature) ? default : Origin.Of(HttpSignatures.Parse(signature)?.KeyId);
|
|
}
|
|
}
|
|
}
|