mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	rate_limit: Add interface to override rate limiting rules.
This commit is contained in:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							7c4da60b53
						
					
				
				
					commit
					34a0139c2b
				
			@@ -275,6 +275,46 @@ strength allowed is controlled by two settings in
 | 
			
		||||
[smokescreen-setup]: deployment.md#customizing-the-outgoing-http-proxy
 | 
			
		||||
[proxy.enable_for_camo]: deployment.md#enable_for_camo
 | 
			
		||||
 | 
			
		||||
## Rate limiting
 | 
			
		||||
 | 
			
		||||
Zulip has built-in rate limiting of login attempts, all access to the
 | 
			
		||||
API, as well as certain other types of actions that may be involved in
 | 
			
		||||
abuse. For example, the email confirmation flow, by its nature, needs
 | 
			
		||||
to allow sending an email to an email address that isn't associated
 | 
			
		||||
with an existing Zulip account. Limiting the ability of users to
 | 
			
		||||
trigger such emails helps prevent bad actors from damaging the spam
 | 
			
		||||
reputation of a Zulip server by sending confirmation emails to random
 | 
			
		||||
email addresses.
 | 
			
		||||
 | 
			
		||||
The default rate limiting rules for a Zulip server will change as we improve
 | 
			
		||||
the product. A server administrator can browse the current rules using
 | 
			
		||||
`/home/zulip/deployments/current/scripts/get-django-setting
 | 
			
		||||
RATE_LIMITING_RULES`; or with comments by reading
 | 
			
		||||
`DEFAULT_RATE_LIMITING_RULES` in `zproject/default_settings.py`.
 | 
			
		||||
 | 
			
		||||
Server administrators can tweak rate limiting in the following ways in
 | 
			
		||||
`/etc/zulip/settings.py`:
 | 
			
		||||
 | 
			
		||||
- The `RATE_LIMITING` setting can be set to `False` to completely
 | 
			
		||||
  disable all rate-limiting.
 | 
			
		||||
- The `RATE_LIMITING_RULES` setting can be used to override specific
 | 
			
		||||
  rules. See the comment in the file for more specific details on how
 | 
			
		||||
  to do it. After changing the setting, we recommend using
 | 
			
		||||
  `/home/zulip/deployments/current/scripts/get-django-setting
 | 
			
		||||
RATE_LIMITING_RULES` to verify your changes. You can then restart
 | 
			
		||||
  the Zulip server with `scripts/restart-server` to have the new
 | 
			
		||||
  configuration take effect.
 | 
			
		||||
- The `RATE_LIMIT_TOR_TOGETHER` setting can be set to `True` to group all
 | 
			
		||||
  known exit nodes of [TOR](https://www.torproject.org/) together for purposes
 | 
			
		||||
  of IP address limiting. Since traffic from a client using TOR is distributed
 | 
			
		||||
  across its exit nodes, without enabling this setting, TOR can otherwise be
 | 
			
		||||
  used to avoid IP-based rate limiting. The updated list of TOR exit nodes
 | 
			
		||||
  is refetched once an hour.
 | 
			
		||||
 | 
			
		||||
See also our [API documentation on rate limiting][rate-limit-api].
 | 
			
		||||
 | 
			
		||||
[rate-limit-api]: https://zulip.com/api/rest-error-handling#rate-limit-exceeded
 | 
			
		||||
 | 
			
		||||
## Final notes and security response
 | 
			
		||||
 | 
			
		||||
If you find some aspect of Zulip that seems inconsistent with this
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@ from .configured_settings import (
 | 
			
		||||
    CUSTOM_HOME_NOT_LOGGED_IN,
 | 
			
		||||
    DEBUG,
 | 
			
		||||
    DEBUG_ERROR_REPORTING,
 | 
			
		||||
    DEFAULT_RATE_LIMITING_RULES,
 | 
			
		||||
    EMAIL_BACKEND,
 | 
			
		||||
    EMAIL_HOST,
 | 
			
		||||
    ERROR_REPORTING,
 | 
			
		||||
@@ -42,6 +43,7 @@ from .configured_settings import (
 | 
			
		||||
    LOCAL_UPLOADS_DIR,
 | 
			
		||||
    MEMCACHED_LOCATION,
 | 
			
		||||
    MEMCACHED_USERNAME,
 | 
			
		||||
    RATE_LIMITING_RULES,
 | 
			
		||||
    REALM_HOSTS,
 | 
			
		||||
    REGISTER_LINK_DISABLED,
 | 
			
		||||
    REMOTE_POSTGRES_HOST,
 | 
			
		||||
@@ -358,34 +360,8 @@ CACHES: Dict[str, Dict[str, object]] = {
 | 
			
		||||
# REDIS-BASED RATE LIMITING CONFIGURATION
 | 
			
		||||
########################################################################
 | 
			
		||||
 | 
			
		||||
RATE_LIMITING_RULES = {
 | 
			
		||||
    "api_by_user": [
 | 
			
		||||
        (60, 200),  # 200 requests max every minute
 | 
			
		||||
    ],
 | 
			
		||||
    "api_by_ip": [
 | 
			
		||||
        (60, 100),
 | 
			
		||||
    ],
 | 
			
		||||
    "api_by_remote_server": [
 | 
			
		||||
        (60, 1000),
 | 
			
		||||
    ],
 | 
			
		||||
    "authenticate_by_username": [
 | 
			
		||||
        (1800, 5),  # 5 failed login attempts within 30 minutes
 | 
			
		||||
    ],
 | 
			
		||||
    "email_change_by_user": [
 | 
			
		||||
        (3600, 2),  # 2 per hour
 | 
			
		||||
        (86400, 5),  # 5 per day
 | 
			
		||||
    ],
 | 
			
		||||
    "password_reset_form_by_email": [
 | 
			
		||||
        (3600, 2),  # 2 reset emails per hour
 | 
			
		||||
        (86400, 5),  # 5 per day
 | 
			
		||||
    ],
 | 
			
		||||
    "sends_email_by_ip": [
 | 
			
		||||
        (86400, 5),
 | 
			
		||||
    ],
 | 
			
		||||
    "spectator_attachment_access_by_file": [
 | 
			
		||||
        (86400, 1000),  # 1000 per day per file
 | 
			
		||||
    ],
 | 
			
		||||
}
 | 
			
		||||
# Merge any local overrides with the default rules.
 | 
			
		||||
RATE_LIMITING_RULES = {**DEFAULT_RATE_LIMITING_RULES, **RATE_LIMITING_RULES}
 | 
			
		||||
 | 
			
		||||
# List of domains that, when applied to a request in a Tornado process,
 | 
			
		||||
# will be handled with the separate in-memory rate limiting backend for Tornado,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import os
 | 
			
		||||
from email.headerregistry import Address
 | 
			
		||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional
 | 
			
		||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
 | 
			
		||||
 | 
			
		||||
from scripts.lib.zulip_tools import deport
 | 
			
		||||
from zproject.settings_types import JwtAuthKey, OIDCIdPConfigDict, SAMLIdPConfigDict
 | 
			
		||||
@@ -198,6 +198,39 @@ RATE_LIMIT_TOR_TOGETHER = False
 | 
			
		||||
SEND_LOGIN_EMAILS = True
 | 
			
		||||
EMBEDDED_BOTS_ENABLED = False
 | 
			
		||||
 | 
			
		||||
DEFAULT_RATE_LIMITING_RULES = {
 | 
			
		||||
    "api_by_user": [
 | 
			
		||||
        (60, 200),  # 200 requests max every minute
 | 
			
		||||
    ],
 | 
			
		||||
    "api_by_ip": [
 | 
			
		||||
        (60, 100),
 | 
			
		||||
    ],
 | 
			
		||||
    "api_by_remote_server": [
 | 
			
		||||
        (60, 1000),
 | 
			
		||||
    ],
 | 
			
		||||
    "authenticate_by_username": [
 | 
			
		||||
        (1800, 5),  # 5 failed login attempts within 30 minutes
 | 
			
		||||
    ],
 | 
			
		||||
    "email_change_by_user": [
 | 
			
		||||
        (3600, 2),  # 2 per hour
 | 
			
		||||
        (86400, 5),  # 5 per day
 | 
			
		||||
    ],
 | 
			
		||||
    "password_reset_form_by_email": [
 | 
			
		||||
        (3600, 2),  # 2 reset emails per hour
 | 
			
		||||
        (86400, 5),  # 5 per day
 | 
			
		||||
    ],
 | 
			
		||||
    "sends_email_by_ip": [
 | 
			
		||||
        (86400, 5),
 | 
			
		||||
    ],
 | 
			
		||||
    "spectator_attachment_access_by_file": [
 | 
			
		||||
        (86400, 1000),  # 1000 per day per file
 | 
			
		||||
    ],
 | 
			
		||||
}
 | 
			
		||||
# Rate limiting defaults can be individually overridden by adding
 | 
			
		||||
# entries in this object, which is merged with
 | 
			
		||||
# DEFAULT_RATE_LIMITING_RULES.
 | 
			
		||||
RATE_LIMITING_RULES: Dict[str, List[Tuple[int, int]]] = {}
 | 
			
		||||
 | 
			
		||||
# Two factor authentication is not yet implementation-complete
 | 
			
		||||
TWO_FACTOR_AUTHENTICATION_ENABLED = False
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -764,6 +764,24 @@ CAMO_URI = "/external_content/"
 | 
			
		||||
## Controls whether Zulip will rate-limit user requests.
 | 
			
		||||
# RATE_LIMITING = True
 | 
			
		||||
 | 
			
		||||
## Entries in this dictionary will override Zulip's default rate
 | 
			
		||||
## limits. Rules which are not explicitly overridden here
 | 
			
		||||
## will be as default. View the current rules using:
 | 
			
		||||
##   /home/zulip/deployments/current/scripts/get-django-setting RATE_LIMITING_RULES
 | 
			
		||||
##
 | 
			
		||||
## The limits are tuples of a number of seconds and a number of
 | 
			
		||||
## requests allowed over that many seconds. If multiple tuples are
 | 
			
		||||
## given in a rule, a request breaching any of them will trigger a
 | 
			
		||||
## rate-limited response to the client. For example, to change the
 | 
			
		||||
## limits for total API requests by each user to be at most 100
 | 
			
		||||
## requests per minute, and at most 200 requests per hour, add:
 | 
			
		||||
##   "api_by_user": [(60, 100), (3600, 200)],
 | 
			
		||||
# RATE_LIMITING_RULES = {
 | 
			
		||||
#     "api_by_ip": [
 | 
			
		||||
#         (60, 100),
 | 
			
		||||
#     ],
 | 
			
		||||
# }
 | 
			
		||||
 | 
			
		||||
## Fetch TOR exit node list every hour, and group all TOR exit nodes
 | 
			
		||||
## together into one bucket when applying rate-limiting.
 | 
			
		||||
# RATE_LIMIT_TOR_TOGETHER = False
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user