f9d3f1ac56
Backend CI / build-and-test (push) Successful in 43s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Successful in 7s
Backend CI / build-and-test (pull_request) Successful in 44s
Frontend Playwright / e2e (pull_request) Has been cancelled
🚀 Create and publish a Docker image / Build & publish backend image (push) Successful in 59s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Has been skipped
🚀 Create and publish a Docker image / Update stack on Portainer (push) Successful in 4s
72 lines
2.1 KiB
C#
72 lines
2.1 KiB
C#
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;
|
|
}
|
|
}
|