aboutsummaryrefslogtreecommitdiff
path: root/clientapi/routing/routing.go
diff options
context:
space:
mode:
authorNeil Alexander <neilalexander@users.noreply.github.com>2020-09-03 10:12:11 +0100
committerGitHub <noreply@github.com>2020-09-03 10:12:11 +0100
commit74743ac8ae3cc439862acd15d13ba4123d745598 (patch)
tree879ff4fca4ae2025b3e57cce8ba060c0fd1b0f73 /clientapi/routing/routing.go
parentd64d0c4be2ab33185b6dd837944dea3268b62c24 (diff)
Rate limiting (#1385)
* Initial rate limiting * Move rate limiting to client API * Update rate limits to hopefully be self-cleaning * Use X-Forwarded-For, add comments * Reduce rate limit threshold * Tweak interval * Configurable backoff * Review comments, set cleanup interval to 30 seconds * Allow generate-config to produce sane CI config * Fix Complement dockerfile
Diffstat (limited to 'clientapi/routing/routing.go')
-rw-r--r--clientapi/routing/routing.go52
1 files changed, 52 insertions, 0 deletions
diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go
index 24343ee1..0c63f968 100644
--- a/clientapi/routing/routing.go
+++ b/clientapi/routing/routing.go
@@ -60,6 +60,7 @@ func Setup(
keyAPI keyserverAPI.KeyInternalAPI,
extRoomsProvider api.ExtraPublicRoomsProvider,
) {
+ rateLimits := newRateLimits(&cfg.RateLimiting)
userInteractiveAuth := auth.NewUserInteractive(accountDB.GetAccountByPassword, cfg)
publicAPIMux.Handle("/versions",
@@ -92,6 +93,9 @@ func Setup(
).Methods(http.MethodPost, http.MethodOptions)
r0mux.Handle("/join/{roomIDOrAlias}",
httputil.MakeAuthAPI(gomatrixserverlib.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
@@ -108,6 +112,9 @@ func Setup(
).Methods(http.MethodGet, http.MethodOptions)
r0mux.Handle("/rooms/{roomID}/join",
httputil.MakeAuthAPI(gomatrixserverlib.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
@@ -119,6 +126,9 @@ func Setup(
).Methods(http.MethodPost, http.MethodOptions)
r0mux.Handle("/rooms/{roomID}/leave",
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
@@ -139,6 +149,9 @@ func Setup(
).Methods(http.MethodPost, http.MethodOptions)
r0mux.Handle("/rooms/{roomID}/invite",
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
@@ -253,14 +266,23 @@ func Setup(
).Methods(http.MethodPut, http.MethodOptions)
r0mux.Handle("/register", httputil.MakeExternalAPI("register", func(req *http.Request) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
return Register(req, userAPI, accountDB, cfg)
})).Methods(http.MethodPost, http.MethodOptions)
v1mux.Handle("/register", httputil.MakeExternalAPI("register", func(req *http.Request) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
return LegacyRegister(req, userAPI, cfg)
})).Methods(http.MethodPost, http.MethodOptions)
r0mux.Handle("/register/available", httputil.MakeExternalAPI("registerAvailable", func(req *http.Request) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
return RegisterAvailable(req, cfg, accountDB)
})).Methods(http.MethodGet, http.MethodOptions)
@@ -332,6 +354,9 @@ func Setup(
r0mux.Handle("/rooms/{roomID}/typing/{userID}",
httputil.MakeAuthAPI("rooms_typing", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
@@ -385,6 +410,9 @@ func Setup(
r0mux.Handle("/account/whoami",
httputil.MakeAuthAPI("whoami", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
return Whoami(req, device)
}),
).Methods(http.MethodGet, http.MethodOptions)
@@ -393,6 +421,9 @@ func Setup(
r0mux.Handle("/login",
httputil.MakeExternalAPI("login", func(req *http.Request) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
return Login(req, accountDB, userAPI, cfg)
}),
).Methods(http.MethodGet, http.MethodPost, http.MethodOptions)
@@ -447,6 +478,9 @@ func Setup(
r0mux.Handle("/profile/{userID}/avatar_url",
httputil.MakeAuthAPI("profile_avatar_url", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
@@ -469,6 +503,9 @@ func Setup(
r0mux.Handle("/profile/{userID}/displayname",
httputil.MakeAuthAPI("profile_displayname", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
@@ -506,6 +543,9 @@ func Setup(
// Riot logs get flooded unless this is handled
r0mux.Handle("/presence/{userID}/status",
httputil.MakeExternalAPI("presence", func(req *http.Request) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
// TODO: Set presence (probably the responsibility of a presence server not clientapi)
return util.JSONResponse{
Code: http.StatusOK,
@@ -516,6 +556,9 @@ func Setup(
r0mux.Handle("/voip/turnServer",
httputil.MakeAuthAPI("turn_server", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
return RequestTurnServer(req, device, cfg)
}),
).Methods(http.MethodGet, http.MethodOptions)
@@ -582,6 +625,9 @@ func Setup(
r0mux.Handle("/user_directory/search",
httputil.MakeAuthAPI("userdirectory_search", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
postContent := struct {
SearchString string `json:"search_term"`
Limit int `json:"limit"`
@@ -623,6 +669,9 @@ func Setup(
r0mux.Handle("/rooms/{roomID}/read_markers",
httputil.MakeExternalAPI("rooms_read_markers", func(req *http.Request) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
// TODO: return the read_markers.
return util.JSONResponse{Code: http.StatusOK, JSON: struct{}{}}
}),
@@ -721,6 +770,9 @@ func Setup(
r0mux.Handle("/capabilities",
httputil.MakeAuthAPI("capabilities", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
+ if r := rateLimits.rateLimit(req); r != nil {
+ return *r
+ }
return GetCapabilities(req, rsAPI)
}),
).Methods(http.MethodGet)