rework server responsibilities (#18)
* rework server responsibilities add remote configuration * start metrics only when compiled as not debug * add some more logging to discord bot * fixes of some casts * make metrics port configurable, minor fixes * add docker bullshit * md formatting * adjustments to docker stuff * fix docker json files, fix some stuff in discord bot, add /useradd for Discord bot * adjust docker configs and fix sharded.bat * fixes for logs, cache file provider repeat trying to open filestream Co-authored-by: rootdarkarchon <root.darkarchon@outlook.com>
This commit is contained in:
		| @@ -1,5 +1,4 @@ | ||||
| using System.Linq; | ||||
| using System.Security.Claims; | ||||
| using System.Security.Claims; | ||||
| using Microsoft.AspNetCore.SignalR; | ||||
|  | ||||
| namespace MareSynchronosServer.Utils; | ||||
| @@ -8,6 +7,6 @@ public class IdBasedUserIdProvider : IUserIdProvider | ||||
| { | ||||
|     public string GetUserId(HubConnectionContext context) | ||||
|     { | ||||
|         return context.User!.Claims.SingleOrDefault(c => string.Equals(c.Type, ClaimTypes.NameIdentifier, System.StringComparison.Ordinal))?.Value; | ||||
|         return context.User!.Claims.SingleOrDefault(c => string.Equals(c.Type, ClaimTypes.NameIdentifier, StringComparison.Ordinal))?.Value; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using MareSynchronosServer.Hubs; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System.Runtime.CompilerServices; | ||||
|  | ||||
| namespace MareSynchronosServer.Utils; | ||||
| @@ -14,6 +13,7 @@ public class MareHubLogger | ||||
|         _hub = hub; | ||||
|         _logger = logger; | ||||
|     } | ||||
|  | ||||
|     public static object[] Args(params object[] args) | ||||
|     { | ||||
|         return args; | ||||
|   | ||||
| @@ -1,8 +1,4 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
|  | ||||
| namespace MareSynchronosServer.Utils; | ||||
| namespace MareSynchronosServer.Utils; | ||||
|  | ||||
| public record PausedEntry | ||||
| { | ||||
|   | ||||
| @@ -1,117 +0,0 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
| using System.Security.Claims; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
| using AspNetCoreRateLimit; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.SignalR; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Options; | ||||
|  | ||||
| namespace MareSynchronosServer.Utils; | ||||
| public class SignalRLimitFilter : IHubFilter | ||||
| { | ||||
|     private readonly IRateLimitProcessor _processor; | ||||
|     private readonly IHttpContextAccessor accessor; | ||||
|     private readonly ILogger<SignalRLimitFilter> logger; | ||||
|     private static readonly SemaphoreSlim ConnectionLimiterSemaphore = new(10); | ||||
|     private static readonly SemaphoreSlim DisconnectLimiterSemaphore = new(10); | ||||
|  | ||||
|     public SignalRLimitFilter( | ||||
|         IOptions<IpRateLimitOptions> options, IProcessingStrategy processing, IIpPolicyStore policyStore, IHttpContextAccessor accessor, ILogger<SignalRLimitFilter> logger) | ||||
|     { | ||||
|         _processor = new IpRateLimitProcessor(options?.Value, policyStore, processing); | ||||
|         this.accessor = accessor; | ||||
|         this.logger = logger; | ||||
|     } | ||||
|  | ||||
|     public async ValueTask<object> InvokeMethodAsync( | ||||
|         HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next) | ||||
|     { | ||||
|         var ip = accessor.GetIpAddress(); | ||||
|         var client = new ClientRequestIdentity | ||||
|         { | ||||
|             ClientIp = ip, | ||||
|             Path = invocationContext.HubMethodName, | ||||
|             HttpVerb = "ws", | ||||
|             ClientId = invocationContext.Context.UserIdentifier | ||||
|         }; | ||||
|         foreach (var rule in await _processor.GetMatchingRulesAsync(client).ConfigureAwait(false)) | ||||
|         { | ||||
|             var counter = await _processor.ProcessRequestAsync(client, rule).ConfigureAwait(false); | ||||
|             if (counter.Count > rule.Limit) | ||||
|             { | ||||
|                 var authUserId = invocationContext.Context.User.Claims?.SingleOrDefault(c => string.Equals(c.Type, ClaimTypes.NameIdentifier, StringComparison.Ordinal))?.Value ?? "Unknown"; | ||||
|                 var retry = counter.Timestamp.RetryAfterFrom(rule); | ||||
|                 logger.LogWarning("Method rate limit triggered from {ip}/{authUserId}: {method}", ip, authUserId, invocationContext.HubMethodName); | ||||
|                 throw new HubException($"call limit {retry}"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return await next(invocationContext).ConfigureAwait(false); | ||||
|     } | ||||
|  | ||||
|     // Optional method | ||||
|     public async Task OnConnectedAsync(HubLifetimeContext context, Func<HubLifetimeContext, Task> next) | ||||
|     { | ||||
|         await ConnectionLimiterSemaphore.WaitAsync().ConfigureAwait(false); | ||||
|         try | ||||
|         { | ||||
|             var ip = accessor.GetIpAddress(); | ||||
|             var client = new ClientRequestIdentity | ||||
|             { | ||||
|                 ClientIp = ip, | ||||
|                 Path = "Connect", | ||||
|                 HttpVerb = "ws", | ||||
|             }; | ||||
|             foreach (var rule in await _processor.GetMatchingRulesAsync(client).ConfigureAwait(false)) | ||||
|             { | ||||
|                 var counter = await _processor.ProcessRequestAsync(client, rule).ConfigureAwait(false); | ||||
|                 if (counter.Count > rule.Limit) | ||||
|                 { | ||||
|                     var retry = counter.Timestamp.RetryAfterFrom(rule); | ||||
|                     logger.LogWarning("Connection rate limit triggered from {ip}", ip); | ||||
|                     ConnectionLimiterSemaphore.Release(); | ||||
|                     throw new HubException($"Connection rate limit {retry}"); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|  | ||||
|             await Task.Delay(25).ConfigureAwait(false); | ||||
|             await next(context).ConfigureAwait(false); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             logger.LogWarning(ex, "Error on OnConnectedAsync"); | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             ConnectionLimiterSemaphore.Release(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public async Task OnDisconnectedAsync( | ||||
|         HubLifetimeContext context, Exception exception, Func<HubLifetimeContext, Exception, Task> next) | ||||
|     { | ||||
|         await DisconnectLimiterSemaphore.WaitAsync().ConfigureAwait(false); | ||||
|         if (exception != null) | ||||
|         { | ||||
|             logger.LogWarning(exception, "InitialException on OnDisconnectedAsync"); | ||||
|         } | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             await next(context, exception).ConfigureAwait(false); | ||||
|             await Task.Delay(25).ConfigureAwait(false); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             logger.LogWarning(e, "ThrownException on OnDisconnectedAsync"); | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             DisconnectLimiterSemaphore.Release(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 rootdarkarchon
					rootdarkarchon