feat: Add request rate limiter based on IP address (#8174)

This commit is contained in:
Daniel
2023-01-06 23:39:02 +11:00
committed by GitHub
parent 0eac5dc6d4
commit 6c79f6a69e
13 changed files with 713 additions and 50 deletions

View File

@@ -411,6 +411,13 @@ module.exports.ParseServerOptions = {
'Configuration for push, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#push-notifications',
action: parsers.objectParser,
},
rateLimit: {
env: 'PARSE_SERVER_RATE_LIMIT',
help:
"Options to limit repeated requests to Parse Server APIs. This can be used to protect sensitive endpoints such as `/requestPasswordReset` from brute-force attacks or Parse Server as a whole from denial-of-service (DoS) attacks.<br><br>\u2139\uFE0F Mind the following limitations:<br>- rate limits applied per IP address; this limits protection against distributed denial-of-service (DDoS) attacks where many requests are coming from various IP addresses<br>- if multiple Parse Server instances are behind a load balancer or ran in a cluster, each instance will calculate it's own request rates, independent from other instances; this limits the applicability of this feature when using a load balancer and another rate limiting solution that takes requests across all instances into account may be more suitable<br>- this feature provides basic protection against denial-of-service attacks, but a more sophisticated solution works earlier in the request flow and prevents a malicious requests to even reach a server instance; it's therefore recommended to implement a solution according to architecture and user case.",
action: parsers.arrayParser,
default: [],
},
readOnlyMasterKey: {
env: 'PARSE_SERVER_READ_ONLY_MASTER_KEY',
help: 'Read-only key, which has the same capabilities as MasterKey without writes',
@@ -516,6 +523,52 @@ module.exports.ParseServerOptions = {
help: 'Key sent with outgoing webhook calls',
},
};
module.exports.RateLimitOptions = {
errorResponseMessage: {
env: 'PARSE_SERVER_RATE_LIMIT_ERROR_RESPONSE_MESSAGE',
help:
'The error message that should be returned in the body of the HTTP 429 response when the rate limit is hit. Default is `Too many requests.`.',
default: 'Too many requests.',
},
includeInternalRequests: {
env: 'PARSE_SERVER_RATE_LIMIT_INCLUDE_INTERNAL_REQUESTS',
help:
'Optional, if `true` the rate limit will also apply to requests that are made in by Cloud Code, default is `false`. Note that a public Cloud Code function that triggers internal requests may circumvent rate limiting and be vulnerable to attacks.',
action: parsers.booleanParser,
default: false,
},
includeMasterKey: {
env: 'PARSE_SERVER_RATE_LIMIT_INCLUDE_MASTER_KEY',
help:
'Optional, if `true` the rate limit will also apply to requests using the `masterKey`, default is `false`. Note that a public Cloud Code function that triggers internal requests using the `masterKey` may circumvent rate limiting and be vulnerable to attacks.',
action: parsers.booleanParser,
default: false,
},
requestCount: {
env: 'PARSE_SERVER_RATE_LIMIT_REQUEST_COUNT',
help:
'The number of requests that can be made per IP address within the time window set in `requestTimeWindow` before the rate limit is applied.',
action: parsers.numberParser('requestCount'),
},
requestMethods: {
env: 'PARSE_SERVER_RATE_LIMIT_REQUEST_METHODS',
help:
'Optional, the HTTP request methods to which the rate limit should be applied, default is all methods.',
action: parsers.arrayParser,
},
requestPath: {
env: 'PARSE_SERVER_RATE_LIMIT_REQUEST_PATH',
help:
'The path of the API route to be rate limited. Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expression. See: https://expressjs.com/en/guide/routing.html',
required: true,
},
requestTimeWindow: {
env: 'PARSE_SERVER_RATE_LIMIT_REQUEST_TIME_WINDOW',
help:
'The window of time in milliseconds within which the number of requests set in `requestCount` can be made before the rate limit is applied.',
action: parsers.numberParser('requestTimeWindow'),
},
};
module.exports.SecurityOptions = {
checkGroups: {
env: 'PARSE_SERVER_SECURITY_CHECK_GROUPS',