ratelimiting.py 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. # Copyright 2014-2016 OpenMarket Ltd
  2. # Copyright 2020 The Matrix.org Foundation C.I.C.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from collections import OrderedDict
  16. from typing import Hashable, Optional, Tuple
  17. from synapse.api.errors import LimitExceededError
  18. from synapse.storage.databases.main import DataStore
  19. from synapse.types import Requester
  20. from synapse.util import Clock
  21. class Ratelimiter:
  22. """
  23. Ratelimit actions marked by arbitrary keys.
  24. Args:
  25. clock: A homeserver clock, for retrieving the current time
  26. rate_hz: The long term number of actions that can be performed in a second.
  27. burst_count: How many actions that can be performed before being limited.
  28. """
  29. def __init__(
  30. self, store: DataStore, clock: Clock, rate_hz: float, burst_count: int
  31. ):
  32. self.clock = clock
  33. self.rate_hz = rate_hz
  34. self.burst_count = burst_count
  35. self.store = store
  36. # A ordered dictionary keeping track of actions, when they were last
  37. # performed and how often. Each entry is a mapping from a key of arbitrary type
  38. # to a tuple representing:
  39. # * How many times an action has occurred since a point in time
  40. # * The point in time
  41. # * The rate_hz of this particular entry. This can vary per request
  42. self.actions: OrderedDict[Hashable, Tuple[float, float, float]] = OrderedDict()
  43. async def can_do_action(
  44. self,
  45. requester: Optional[Requester],
  46. key: Optional[Hashable] = None,
  47. rate_hz: Optional[float] = None,
  48. burst_count: Optional[int] = None,
  49. update: bool = True,
  50. n_actions: int = 1,
  51. _time_now_s: Optional[float] = None,
  52. ) -> Tuple[bool, float]:
  53. """Can the entity (e.g. user or IP address) perform the action?
  54. Checks if the user has ratelimiting disabled in the database by looking
  55. for null/zero values in the `ratelimit_override` table. (Non-zero
  56. values aren't honoured, as they're specific to the event sending
  57. ratelimiter, rather than all ratelimiters)
  58. Args:
  59. requester: The requester that is doing the action, if any. Used to check
  60. if the user has ratelimits disabled in the database.
  61. key: An arbitrary key used to classify an action. Defaults to the
  62. requester's user ID.
  63. rate_hz: The long term number of actions that can be performed in a second.
  64. Overrides the value set during instantiation if set.
  65. burst_count: How many actions that can be performed before being limited.
  66. Overrides the value set during instantiation if set.
  67. update: Whether to count this check as performing the action
  68. n_actions: The number of times the user wants to do this action. If the user
  69. cannot do all of the actions, the user's action count is not incremented
  70. at all.
  71. _time_now_s: The current time. Optional, defaults to the current time according
  72. to self.clock. Only used by tests.
  73. Returns:
  74. A tuple containing:
  75. * A bool indicating if they can perform the action now
  76. * The reactor timestamp for when the action can be performed next.
  77. -1 if rate_hz is less than or equal to zero
  78. """
  79. if key is None:
  80. if not requester:
  81. raise ValueError("Must supply at least one of `requester` or `key`")
  82. key = requester.user.to_string()
  83. if requester:
  84. # Disable rate limiting of users belonging to any AS that is configured
  85. # not to be rate limited in its registration file (rate_limited: true|false).
  86. if requester.app_service and not requester.app_service.is_rate_limited():
  87. return True, -1.0
  88. # Check if ratelimiting has been disabled for the user.
  89. #
  90. # Note that we don't use the returned rate/burst count, as the table
  91. # is specifically for the event sending ratelimiter. Instead, we
  92. # only use it to (somewhat cheekily) infer whether the user should
  93. # be subject to any rate limiting or not.
  94. override = await self.store.get_ratelimit_for_user(
  95. requester.authenticated_entity
  96. )
  97. if override and not override.messages_per_second:
  98. return True, -1.0
  99. # Override default values if set
  100. time_now_s = _time_now_s if _time_now_s is not None else self.clock.time()
  101. rate_hz = rate_hz if rate_hz is not None else self.rate_hz
  102. burst_count = burst_count if burst_count is not None else self.burst_count
  103. # Remove any expired entries
  104. self._prune_message_counts(time_now_s)
  105. # Check if there is an existing count entry for this key
  106. action_count, time_start, _ = self.actions.get(key, (0.0, time_now_s, 0.0))
  107. # Check whether performing another action is allowed
  108. time_delta = time_now_s - time_start
  109. performed_count = action_count - time_delta * rate_hz
  110. if performed_count < 0:
  111. performed_count = 0
  112. time_start = time_now_s
  113. # This check would be easier read as performed_count + n_actions > burst_count,
  114. # but performed_count might be a very precise float (with lots of numbers
  115. # following the point) in which case Python might round it up when adding it to
  116. # n_actions. Writing it this way ensures it doesn't happen.
  117. if performed_count > burst_count - n_actions:
  118. # Deny, we have exceeded our burst count
  119. allowed = False
  120. else:
  121. # We haven't reached our limit yet
  122. allowed = True
  123. action_count = performed_count + n_actions
  124. if update:
  125. self.actions[key] = (action_count, time_start, rate_hz)
  126. if rate_hz > 0:
  127. # Find out when the count of existing actions expires
  128. time_allowed = time_start + (action_count - burst_count + 1) / rate_hz
  129. # Don't give back a time in the past
  130. if time_allowed < time_now_s:
  131. time_allowed = time_now_s
  132. else:
  133. # XXX: Why is this -1? This seems to only be used in
  134. # self.ratelimit. I guess so that clients get a time in the past and don't
  135. # feel afraid to try again immediately
  136. time_allowed = -1
  137. return allowed, time_allowed
  138. def _prune_message_counts(self, time_now_s: float):
  139. """Remove message count entries that have not exceeded their defined
  140. rate_hz limit
  141. Args:
  142. time_now_s: The current time
  143. """
  144. # We create a copy of the key list here as the dictionary is modified during
  145. # the loop
  146. for key in list(self.actions.keys()):
  147. action_count, time_start, rate_hz = self.actions[key]
  148. # Rate limit = "seconds since we started limiting this action" * rate_hz
  149. # If this limit has not been exceeded, wipe our record of this action
  150. time_delta = time_now_s - time_start
  151. if action_count - time_delta * rate_hz > 0:
  152. continue
  153. else:
  154. del self.actions[key]
  155. async def ratelimit(
  156. self,
  157. requester: Optional[Requester],
  158. key: Optional[Hashable] = None,
  159. rate_hz: Optional[float] = None,
  160. burst_count: Optional[int] = None,
  161. update: bool = True,
  162. n_actions: int = 1,
  163. _time_now_s: Optional[float] = None,
  164. ):
  165. """Checks if an action can be performed. If not, raises a LimitExceededError
  166. Checks if the user has ratelimiting disabled in the database by looking
  167. for null/zero values in the `ratelimit_override` table. (Non-zero
  168. values aren't honoured, as they're specific to the event sending
  169. ratelimiter, rather than all ratelimiters)
  170. Args:
  171. requester: The requester that is doing the action, if any. Used to check for
  172. if the user has ratelimits disabled.
  173. key: An arbitrary key used to classify an action. Defaults to the
  174. requester's user ID.
  175. rate_hz: The long term number of actions that can be performed in a second.
  176. Overrides the value set during instantiation if set.
  177. burst_count: How many actions that can be performed before being limited.
  178. Overrides the value set during instantiation if set.
  179. update: Whether to count this check as performing the action
  180. n_actions: The number of times the user wants to do this action. If the user
  181. cannot do all of the actions, the user's action count is not incremented
  182. at all.
  183. _time_now_s: The current time. Optional, defaults to the current time according
  184. to self.clock. Only used by tests.
  185. Raises:
  186. LimitExceededError: If an action could not be performed, along with the time in
  187. milliseconds until the action can be performed again
  188. """
  189. time_now_s = _time_now_s if _time_now_s is not None else self.clock.time()
  190. allowed, time_allowed = await self.can_do_action(
  191. requester,
  192. key,
  193. rate_hz=rate_hz,
  194. burst_count=burst_count,
  195. update=update,
  196. n_actions=n_actions,
  197. _time_now_s=time_now_s,
  198. )
  199. if not allowed:
  200. raise LimitExceededError(
  201. retry_after_ms=int(1000 * (time_allowed - time_now_s))
  202. )