Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

214 řádky
7.3 KiB

  1. # Copyright 2014-2016 OpenMarket Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from typing import Any, Dict, Optional, cast
  15. import attr
  16. from synapse.types import JsonDict
  17. from ._base import Config
  18. @attr.s(slots=True, frozen=True, auto_attribs=True)
  19. class RatelimitSettings:
  20. key: str
  21. per_second: float
  22. burst_count: int
  23. @classmethod
  24. def parse(
  25. cls,
  26. config: Dict[str, Any],
  27. key: str,
  28. defaults: Optional[Dict[str, float]] = None,
  29. ) -> "RatelimitSettings":
  30. """Parse config[key] as a new-style rate limiter config.
  31. The key may refer to a nested dictionary using a full stop (.) to separate
  32. each nested key. For example, use the key "a.b.c" to parse the following:
  33. a:
  34. b:
  35. c:
  36. per_second: 10
  37. burst_count: 200
  38. If this lookup fails, we'll fallback to the defaults.
  39. """
  40. defaults = defaults or {"per_second": 0.17, "burst_count": 3.0}
  41. rl_config = config
  42. for part in key.split("."):
  43. rl_config = rl_config.get(part, {})
  44. # By this point we should have hit the rate limiter parameters.
  45. # We don't actually check this though!
  46. rl_config = cast(Dict[str, float], rl_config)
  47. return cls(
  48. key=key,
  49. per_second=rl_config.get("per_second", defaults["per_second"]),
  50. burst_count=int(rl_config.get("burst_count", defaults["burst_count"])),
  51. )
  52. @attr.s(auto_attribs=True)
  53. class FederationRatelimitSettings:
  54. window_size: int = 1000
  55. sleep_limit: int = 10
  56. sleep_delay: int = 500
  57. reject_limit: int = 50
  58. concurrent: int = 3
  59. class RatelimitConfig(Config):
  60. section = "ratelimiting"
  61. def read_config(self, config: JsonDict, **kwargs: Any) -> None:
  62. # Load the new-style messages config if it exists. Otherwise fall back
  63. # to the old method.
  64. if "rc_message" in config:
  65. self.rc_message = RatelimitSettings.parse(
  66. config, "rc_message", defaults={"per_second": 0.2, "burst_count": 10.0}
  67. )
  68. else:
  69. self.rc_message = RatelimitSettings(
  70. key="rc_messages",
  71. per_second=config.get("rc_messages_per_second", 0.2),
  72. burst_count=config.get("rc_message_burst_count", 10.0),
  73. )
  74. # Load the new-style federation config, if it exists. Otherwise, fall
  75. # back to the old method.
  76. if "rc_federation" in config:
  77. self.rc_federation = FederationRatelimitSettings(**config["rc_federation"])
  78. else:
  79. self.rc_federation = FederationRatelimitSettings(
  80. **{
  81. k: v
  82. for k, v in {
  83. "window_size": config.get("federation_rc_window_size"),
  84. "sleep_limit": config.get("federation_rc_sleep_limit"),
  85. "sleep_delay": config.get("federation_rc_sleep_delay"),
  86. "reject_limit": config.get("federation_rc_reject_limit"),
  87. "concurrent": config.get("federation_rc_concurrent"),
  88. }.items()
  89. if v is not None
  90. }
  91. )
  92. self.rc_registration = RatelimitSettings.parse(config, "rc_registration", {})
  93. self.rc_registration_token_validity = RatelimitSettings.parse(
  94. config,
  95. "rc_registration_token_validity",
  96. defaults={"per_second": 0.1, "burst_count": 5},
  97. )
  98. # It is reasonable to login with a bunch of devices at once (i.e. when
  99. # setting up an account), but it is *not* valid to continually be
  100. # logging into new devices.
  101. self.rc_login_address = RatelimitSettings.parse(
  102. config,
  103. "rc_login.address",
  104. defaults={"per_second": 0.003, "burst_count": 5},
  105. )
  106. self.rc_login_account = RatelimitSettings.parse(
  107. config,
  108. "rc_login.account",
  109. defaults={"per_second": 0.003, "burst_count": 5},
  110. )
  111. self.rc_login_failed_attempts = RatelimitSettings.parse(
  112. config,
  113. "rc_login.failed_attempts",
  114. {},
  115. )
  116. self.federation_rr_transactions_per_room_per_second = config.get(
  117. "federation_rr_transactions_per_room_per_second", 50
  118. )
  119. self.rc_admin_redaction = None
  120. if "rc_admin_redaction" in config:
  121. self.rc_admin_redaction = RatelimitSettings.parse(
  122. config, "rc_admin_redaction", {}
  123. )
  124. self.rc_joins_local = RatelimitSettings.parse(
  125. config,
  126. "rc_joins.local",
  127. defaults={"per_second": 0.1, "burst_count": 10},
  128. )
  129. self.rc_joins_remote = RatelimitSettings.parse(
  130. config,
  131. "rc_joins.remote",
  132. defaults={"per_second": 0.01, "burst_count": 10},
  133. )
  134. # Track the rate of joins to a given room. If there are too many, temporarily
  135. # prevent local joins and remote joins via this server.
  136. self.rc_joins_per_room = RatelimitSettings.parse(
  137. config,
  138. "rc_joins_per_room",
  139. defaults={"per_second": 1, "burst_count": 10},
  140. )
  141. # Ratelimit cross-user key requests:
  142. # * For local requests this is keyed by the sending device.
  143. # * For requests received over federation this is keyed by the origin.
  144. #
  145. # Note that this isn't exposed in the configuration as it is obscure.
  146. self.rc_key_requests = RatelimitSettings.parse(
  147. config,
  148. "rc_key_requests",
  149. defaults={"per_second": 20, "burst_count": 100},
  150. )
  151. self.rc_3pid_validation = RatelimitSettings.parse(
  152. config,
  153. "rc_3pid_validation",
  154. defaults={"per_second": 0.003, "burst_count": 5},
  155. )
  156. self.rc_invites_per_room = RatelimitSettings.parse(
  157. config,
  158. "rc_invites.per_room",
  159. defaults={"per_second": 0.3, "burst_count": 10},
  160. )
  161. self.rc_invites_per_user = RatelimitSettings.parse(
  162. config,
  163. "rc_invites.per_user",
  164. defaults={"per_second": 0.003, "burst_count": 5},
  165. )
  166. self.rc_invites_per_issuer = RatelimitSettings.parse(
  167. config,
  168. "rc_invites.per_issuer",
  169. defaults={"per_second": 0.3, "burst_count": 10},
  170. )
  171. self.rc_third_party_invite = RatelimitSettings.parse(
  172. config,
  173. "rc_third_party_invite",
  174. defaults={"per_second": 0.0025, "burst_count": 5},
  175. )
  176. # Ratelimit create media requests:
  177. self.rc_media_create = RatelimitSettings.parse(
  178. config,
  179. "rc_media_create",
  180. defaults={"per_second": 10, "burst_count": 50},
  181. )