diff --git a/package.json b/package.json index 2b98f59..dcbca32 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cosmos-server", - "version": "0.3.0-unstable17", + "version": "0.3.0-unstable18", "description": "", "main": "test-server.js", "bugs": { diff --git a/readme.md b/readme.md index d3813b3..6c39b38 100644 --- a/readme.md +++ b/readme.md @@ -48,7 +48,7 @@ Key Features: * **Dynamic Rate Limiting** ✨ SmartShield calculates rate limits based on user behavior, providing a flexible approach to maintain API health without negatively impacting user experience. * **Adaptive Actions** 📈 SmartShield automatically throttles users who exceed their rate limits, preventing them from consuming more resources than they are allowed without abruptly terminating their requests. * **User Bans & Strikes** 🚫 Implement temporary or permanent bans and issue strikes automatically to prevent API abuse from malicious or resource-intensive users. - * **Global Request Control** 🌐 Monitor and limit the total number of simultaneous requests on your server, ensuring optimal performance and stability. + * **Global Request Control** 🌐 Monitor and limit with queues the total number of simultaneous requests on your server, ensuring optimal performance and stability. * **User-based Metrics** 📊 SmartShield tracks user consumption in terms of requests, data usage, and simultaneous connections, allowing for detailed control. * **Privileged Access** 🔑 Assign privileged access to specific user groups, granting them exemption from certain restrictions and ensuring uninterrupted service even durin attacks. * **Customizable Policies** ⚙️ Modify SmartShield's default policies to suit your specific needs, such as request limits, time budgets, and more. diff --git a/src/proxy/shield.go b/src/proxy/shield.go index 931eb09..119f98e 100644 --- a/src/proxy/shield.go +++ b/src/proxy/shield.go @@ -149,7 +149,7 @@ func (shield *smartShieldState) isAllowedToReqest(policy utils.SmartShieldPolicy if (userConsumed.Time > (policy.PerUserTimeBudget * float64(policy.PolicyStrictness))) || (userConsumed.Requests > (policy.PerUserRequestLimit * policy.PolicyStrictness)) || (userConsumed.Bytes > (policy.PerUserByteLimit * int64(policy.PolicyStrictness))) || - (userConsumed.Simultaneous > (policy.PerUserSimultaneous * policy.PolicyStrictness)) { + (userConsumed.Simultaneous > (policy.PerUserSimultaneous * policy.PolicyStrictness * 15)) { shield.bans = append(shield.bans, &userBan{ ClientID: ClientID, banType: STRIKE, @@ -259,10 +259,26 @@ func SmartShieldMiddleware(policy utils.SmartShieldPolicy) func(http.Handler) ht currentGlobalRequests := shield.GetServerNbReq() + 1 utils.Debug(fmt.Sprintf("SmartShield: Current global requests: %d", currentGlobalRequests)) - if currentGlobalRequests > policy.MaxGlobalSimultaneous && !isPrivileged(r, policy) { - utils.Log("SmartShield: Too many users on the server") - http.Error(w, "Too many requests", http.StatusTooManyRequests) - return + if !isPrivileged(r, policy) { + tooManyReq := currentGlobalRequests > policy.MaxGlobalSimultaneous + wayTooManyReq := currentGlobalRequests > policy.MaxGlobalSimultaneous * 10 + retries := 50 + if wayTooManyReq { + utils.Log("SmartShield: WAYYYY Too many users on the server. Aborting right away.") + http.Error(w, "Too many requests", http.StatusTooManyRequests) + return + } + for tooManyReq { + time.Sleep(5000 * time.Millisecond) + currentGlobalRequests := shield.GetServerNbReq() + 1 + tooManyReq = currentGlobalRequests > policy.MaxGlobalSimultaneous + retries-- + if retries <= 0 { + utils.Log("SmartShield: Too many users on the server") + http.Error(w, "Too many requests", http.StatusTooManyRequests) + return + } + } } clientID := GetClientID(r)