Dev #24

Closed
serega404 wants to merge 1 commits from dev into main
3 changed files with 80 additions and 0 deletions
Showing only changes of commit f9d3f1ac56 - Show all commits
@@ -0,0 +1,71 @@
using System.Net;
using System.Net.Sockets;
namespace UniVerse.Api.Middleware;
public sealed class LocalNetworksOnlyMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<LocalNetworksOnlyMiddleware> _logger;
public LocalNetworksOnlyMiddleware(RequestDelegate next, ILogger<LocalNetworksOnlyMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var remoteIpAddress = context.Connection.RemoteIpAddress;
if (remoteIpAddress is null || !IsLocalNetwork(remoteIpAddress))
{
_logger.LogWarning("Blocked metrics request from non-local address {RemoteIpAddress}", remoteIpAddress);
context.Response.StatusCode = StatusCodes.Status403Forbidden;
await context.Response.WriteAsync("Metrics endpoint is available only from local networks.");
return;
}
await _next(context);
}
private static bool IsLocalNetwork(IPAddress ipAddress)
{
if (IPAddress.IsLoopback(ipAddress))
{
return true;
}
if (ipAddress.IsIPv4MappedToIPv6)
{
ipAddress = ipAddress.MapToIPv4();
}
return ipAddress.AddressFamily switch
{
AddressFamily.InterNetwork => IsPrivateOrLinkLocalIPv4(ipAddress),
AddressFamily.InterNetworkV6 => IsPrivateOrLinkLocalIPv6(ipAddress),
_ => false
};
}
private static bool IsPrivateOrLinkLocalIPv4(IPAddress ipAddress)
{
var bytes = ipAddress.GetAddressBytes();
return bytes[0] == 10
|| bytes[0] == 127
|| (bytes[0] == 192 && bytes[1] == 168)
|| (bytes[0] == 172 && bytes[1] is >= 16 and <= 31)
|| (bytes[0] == 169 && bytes[1] == 254);
}
private static bool IsPrivateOrLinkLocalIPv6(IPAddress ipAddress)
{
var bytes = ipAddress.GetAddressBytes();
return ipAddress.IsIPv6LinkLocal
|| ipAddress.IsIPv6SiteLocal
|| (bytes[0] & 0xfe) == 0xfc;
}
}
+8
View File
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi;
using Prometheus;
using Quartz;
using Serilog;
using UniVerse.Api.BackgroundServices;
@@ -221,6 +222,7 @@ if (app.Environment.IsDevelopment())
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpMetrics();
if (app.Environment.IsDevelopment())
{
app.UseAntiforgery();
@@ -228,4 +230,10 @@ if (app.Environment.IsDevelopment())
}
app.MapControllers();
// Restrict Prometheus scrape endpoint to local and private networks.
app.UseWhen(
context => context.Request.Path.StartsWithSegments("/metrics", StringComparison.OrdinalIgnoreCase),
branch => branch.UseMiddleware<LocalNetworksOnlyMiddleware>());
app.MapMetrics();
app.Run();
+1
View File
@@ -30,6 +30,7 @@
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.1" />
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.18.1" />
<PackageReference Include="prometheus-net.AspNetCore" Version="8.2.1" />
</ItemGroup>
<ItemGroup>