Add some better ratelimiting to email sending (#526)
This commit is contained in:
parent
f86eb4126e
commit
37bd539ed7
1
changelog.d/526.misc
Normal file
1
changelog.d/526.misc
Normal file
@ -0,0 +1 @@
|
||||
Add ratelimiting to email sending.
|
@ -45,6 +45,8 @@ email.smtphost = localhost
|
||||
email.from = Sydent Validation <noreply@localhost>
|
||||
email.smtpport = 9925
|
||||
email.subject = Your Validation Token
|
||||
email.ratelimit_sender.burst = 100000
|
||||
email.ratelimit_sender.rate_hz = 100000
|
||||
"""
|
||||
|
||||
|
||||
|
@ -70,4 +70,11 @@ class EmailConfig(BaseConfig):
|
||||
"email", "email.third_party_invite_domain_obfuscate_characters"
|
||||
)
|
||||
|
||||
self.email_sender_ratelimit_burst = cfg.getint(
|
||||
"email", "email.ratelimit_sender.burst", fallback=5
|
||||
)
|
||||
self.email_sender_ratelimit_rate_hz = cfg.getfloat(
|
||||
"email", "email.ratelimit_sender.rate_hz", fallback=1.0 / (5 * 60.0)
|
||||
)
|
||||
|
||||
return False
|
||||
|
@ -44,8 +44,16 @@ class EmailRequestCodeServlet(Resource):
|
||||
def render_POST(self, request: Request) -> JsonDict:
|
||||
send_cors(request)
|
||||
|
||||
ipaddress = self.sydent.ip_from_request(request)
|
||||
|
||||
if self.require_auth:
|
||||
authV2(self.sydent, request)
|
||||
account = authV2(self.sydent, request)
|
||||
|
||||
self.sydent.email_sender_ratelimiter.ratelimit(account.userId)
|
||||
elif ipaddress:
|
||||
# For `/v1/` requests the ip address is the best we can do for rate
|
||||
# limiting.
|
||||
self.sydent.email_sender_ratelimiter.ratelimit(ipaddress)
|
||||
|
||||
args = get_args(request, ("email", "client_secret", "send_attempt"))
|
||||
|
||||
@ -84,7 +92,6 @@ class EmailRequestCodeServlet(Resource):
|
||||
request.setResponseCode(400)
|
||||
return {"errcode": "M_INVALID_PARAM", "error": "Invalid email provided"}
|
||||
|
||||
ipaddress = self.sydent.ip_from_request(request)
|
||||
brand = self.sydent.brand_from_request(request)
|
||||
|
||||
nextLink: Optional[str] = None
|
||||
|
@ -12,6 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
import random
|
||||
import string
|
||||
from email.header import Header
|
||||
@ -31,6 +32,8 @@ from sydent.types import JsonDict
|
||||
from sydent.util.emailutils import EmailAddressException, sendEmail
|
||||
from sydent.util.stringutils import MAX_EMAIL_ADDRESS_LENGTH, normalise_address
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sydent.sydent import Sydent
|
||||
|
||||
@ -69,6 +72,12 @@ class StoreInviteServlet(Resource):
|
||||
if account.userId != sender:
|
||||
raise MatrixRestError(403, "M_UNAUTHORIZED", "'sender' doesn't match")
|
||||
|
||||
self.sydent.email_sender_ratelimiter.ratelimit(sender)
|
||||
|
||||
logger.info(
|
||||
"Store invite request from %s to %s, in %s", sender, address, roomId
|
||||
)
|
||||
|
||||
globalAssocStore = GlobalAssociationStore(self.sydent)
|
||||
mxid = globalAssocStore.getMxid(medium, normalised_address)
|
||||
if mxid:
|
||||
|
@ -81,6 +81,7 @@ from sydent.http.servlets.v2_servlet import V2Servlet
|
||||
from sydent.replication.pusher import Pusher
|
||||
from sydent.threepid.bind import ThreepidBinder
|
||||
from sydent.util.hash import sha256_and_url_safe_base64
|
||||
from sydent.util.ratelimiter import Ratelimiter
|
||||
from sydent.util.tokenutils import generateAlphanumericTokenOfLength
|
||||
from sydent.validators.emailvalidator import EmailValidator
|
||||
from sydent.validators.msisdnvalidator import MsisdnValidator
|
||||
@ -169,6 +170,12 @@ class Sydent:
|
||||
|
||||
self.pusher: Pusher = Pusher(self)
|
||||
|
||||
self.email_sender_ratelimiter: Ratelimiter[str] = Ratelimiter(
|
||||
self.reactor,
|
||||
burst=self.config.email.email_sender_ratelimit_burst,
|
||||
rate_hz=self.config.email.email_sender_ratelimit_rate_hz,
|
||||
)
|
||||
|
||||
def run(self) -> None:
|
||||
self.clientApiHttpServer.setup()
|
||||
self.replicationHttpsServer.setup()
|
||||
|
Loading…
x
Reference in New Issue
Block a user