65 lines
2.8 KiB
C#
65 lines
2.8 KiB
C#
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.HttpOverrides;
|
|
using System.Net;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.Security;
|
|
|
|
/// <summary>
|
|
/// Config shape for trusted-proxy forwarded-header handling
|
|
/// (<c>ScadaBridge:Security:ForwardedHeaders</c>). Disabled by default: a deployment
|
|
/// with no reverse proxy must NOT honor X-Forwarded-For (a client could spoof its
|
|
/// throttle key). The documented Traefik topologies enable it with the docker
|
|
/// network range so LoginThrottle keys on the REAL client IP (arch-review R2 N2).
|
|
/// </summary>
|
|
public sealed class ForwardedHeadersSecurityOptions
|
|
{
|
|
/// <summary>Configuration section binding this options class.</summary>
|
|
public const string SectionName = "ScadaBridge:Security:ForwardedHeaders";
|
|
|
|
/// <summary>Whether X-Forwarded-For from trusted proxies is honored.</summary>
|
|
public bool Enabled { get; set; }
|
|
|
|
/// <summary>Exact proxy IPs allowed to supply X-Forwarded-For.</summary>
|
|
public string[] KnownProxies { get; set; } = [];
|
|
|
|
/// <summary>CIDR networks allowed to supply X-Forwarded-For (e.g. "172.16.0.0/12").</summary>
|
|
public string[] KnownNetworks { get; set; } = [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Builds the <see cref="ForwardedHeadersOptions"/> for <c>app.UseForwardedHeaders</c>.
|
|
/// Pure and fail-fast: malformed entries throw at startup rather than silently
|
|
/// trusting nothing/everything. Defaults (loopback) are CLEARED — only the
|
|
/// explicitly configured proxies/networks are trusted, and ForwardLimit=1 means
|
|
/// only the entry the trusted proxy itself appended is honored.
|
|
/// </summary>
|
|
public static class ForwardedHeadersSetup
|
|
{
|
|
/// <summary>
|
|
/// Builds the forwarded-headers options, or <see langword="null"/> when disabled.
|
|
/// </summary>
|
|
/// <param name="options">The bound <see cref="ForwardedHeadersSecurityOptions"/>.</param>
|
|
/// <returns>The configured <see cref="ForwardedHeadersOptions"/>, or <see langword="null"/> when disabled.</returns>
|
|
public static ForwardedHeadersOptions? Build(ForwardedHeadersSecurityOptions options)
|
|
{
|
|
if (!options.Enabled) return null;
|
|
var built = new ForwardedHeadersOptions
|
|
{
|
|
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
|
|
ForwardLimit = 1,
|
|
};
|
|
built.KnownProxies.Clear();
|
|
// KnownIPNetworks (System.Net.IPNetwork) is the net10 successor to the now-deprecated
|
|
// KnownNetworks; UseForwardedHeaders reads it identically.
|
|
built.KnownIPNetworks.Clear();
|
|
foreach (var proxy in options.KnownProxies)
|
|
built.KnownProxies.Add(IPAddress.Parse(proxy));
|
|
foreach (var network in options.KnownNetworks)
|
|
{
|
|
var parts = network.Split('/');
|
|
built.KnownIPNetworks.Add(new(IPAddress.Parse(parts[0]), int.Parse(parts[1])));
|
|
}
|
|
return built;
|
|
}
|
|
}
|