diff --git a/LightlessSyncServer/LightlessSyncAuthService/Controllers/JwtController.cs b/LightlessSyncServer/LightlessSyncAuthService/Controllers/JwtController.cs index f89946b..adb8d98 100644 --- a/LightlessSyncServer/LightlessSyncAuthService/Controllers/JwtController.cs +++ b/LightlessSyncServer/LightlessSyncAuthService/Controllers/JwtController.cs @@ -1,5 +1,6 @@ using LightlessSync.API.Routes; using LightlessSyncAuthService.Services; +using LightlessSyncAuthService.Utils; using LightlessSyncShared; using LightlessSyncShared.Data; using LightlessSyncShared.Services; diff --git a/LightlessSyncServer/LightlessSyncAuthService/Controllers/OAuthController.cs b/LightlessSyncServer/LightlessSyncAuthService/Controllers/OAuthController.cs index e3c4916..5d7215f 100644 --- a/LightlessSyncServer/LightlessSyncAuthService/Controllers/OAuthController.cs +++ b/LightlessSyncServer/LightlessSyncAuthService/Controllers/OAuthController.cs @@ -1,5 +1,6 @@ using LightlessSync.API.Routes; using LightlessSyncAuthService.Services; +using LightlessSyncAuthService.Utils; using LightlessSyncShared; using LightlessSyncShared.Data; using LightlessSyncShared.Services; diff --git a/LightlessSyncServer/LightlessSyncAuthService/Services/GeoIPService.cs b/LightlessSyncServer/LightlessSyncAuthService/Services/GeoIPService.cs index f3b0c4b..84ea008 100644 --- a/LightlessSyncServer/LightlessSyncAuthService/Services/GeoIPService.cs +++ b/LightlessSyncServer/LightlessSyncAuthService/Services/GeoIPService.cs @@ -1,9 +1,11 @@ -using LightlessSyncShared; +using LightlessSyncAuthService.Utils; +using LightlessSyncShared; using LightlessSyncShared.Services; using LightlessSyncShared.Utils.Configuration; using MaxMind.GeoIP2; using MaxMind.GeoIP2.Model; using Microsoft.AspNetCore.Http; +using System.Net; using System.Security.Claims; namespace LightlessSyncAuthService.Services; @@ -35,7 +37,9 @@ public class GeoIPService : IHostedService try { - var ip = httpContextAccessor.GetIpAddress(); + var ip = httpContextAccessor.GetClientIpAddress(); + if (ip is null || IPAddress.IsLoopback(ip)) + return "*"; using CancellationTokenSource waitCts = new(); waitCts.CancelAfter(TimeSpan.FromSeconds(5)); @@ -148,33 +152,29 @@ public class GeoIPService : IHostedService internal async Task GetCountryFromIP(IHttpContextAccessor httpContextAccessor) { if (!_useGeoIP) - { return "*"; - } + + var ip = httpContextAccessor.GetClientIpAddress(); + if (ip is null || IPAddress.IsLoopback(ip)) + return "*"; try { - var ip = httpContextAccessor.GetIpAddress(); - - using CancellationTokenSource waitCts = new(); - waitCts.CancelAfter(TimeSpan.FromSeconds(5)); - while (_processingReload) await Task.Delay(100, waitCts.Token).ConfigureAwait(false); + using CancellationTokenSource waitCts = new(TimeSpan.FromSeconds(5)); + while (_processingReload) + await Task.Delay(100, waitCts.Token).ConfigureAwait(false); if (_dbReader!.TryCity(ip, out var response)) { - string? country = response?.Country.IsoCode; - - if (!string.IsNullOrEmpty(country) - && response?.Location.Longitude != null) - { - return country; - } + var country = response?.Country?.IsoCode; + return !string.IsNullOrEmpty(country) ? country : "*"; } + return "*"; } catch (Exception ex) { - _logger.LogWarning(ex, "Error handling Geo IP country in request"); + _logger.LogError(ex, "GeoIP lookup failed for {Ip}", ip); return "*"; } } diff --git a/LightlessSyncServer/LightlessSyncAuthService/Utils/HttpContextAccessorExtensions.cs b/LightlessSyncServer/LightlessSyncAuthService/Utils/HttpContextAccessorExtensions.cs new file mode 100644 index 0000000..8d3e11d --- /dev/null +++ b/LightlessSyncServer/LightlessSyncAuthService/Utils/HttpContextAccessorExtensions.cs @@ -0,0 +1,26 @@ +using System.Net; + +namespace LightlessSyncAuthService.Utils +{ + public static class HttpContextAccessorExtensions + { + public static IPAddress? GetClientIpAddress(this IHttpContextAccessor accessor) + { + var context = accessor.HttpContext; + if (context == null) return null; + + string[] headerKeys = { "CF-Connecting-IP", "X-Forwarded-For", "X-Real-IP" }; + foreach (var key in headerKeys) + { + if (context.Request.Headers.TryGetValue(key, out var values)) + { + var ipCandidate = values.FirstOrDefault()?.Split(',').FirstOrDefault()?.Trim(); + if (IPAddress.TryParse(ipCandidate, out var parsed)) + return parsed; + } + } + + return context.Connection?.RemoteIpAddress; + } + } +} \ No newline at end of file