1+ using System . Net ;
2+ using System . Net . Sockets ;
13using System . Text . Json . Serialization ;
24using System . Text . RegularExpressions ;
35using CodeSecure . Application ;
1012using Microsoft . AspNetCore . Mvc . ApplicationModels ;
1113using Scalar . AspNetCore ;
1214using Serilog ;
15+ using IPNetwork = Microsoft . AspNetCore . HttpOverrides . IPNetwork ;
1316
1417namespace CodeSecure . Api ;
1518
@@ -20,7 +23,9 @@ public static void Run(string[] args)
2023 var builder = WebApplication . CreateBuilder ( args ) ;
2124 builder . Services . Configure < ForwardedHeadersOptions > ( options =>
2225 {
23- options . ForwardedHeaders = ForwardedHeaders . XForwardedProto | ForwardedHeaders . XForwardedHost ;
26+ options . ForwardedHeaders = ForwardedHeaders . XForwardedProto | ForwardedHeaders . XForwardedHost |
27+ ForwardedHeaders . XForwardedFor ;
28+ options . AddTrustedProxies ( Configuration . TrustedProxies ) ;
2429 } ) ;
2530 builder . Host . UseSerilog ( ( context , configuration ) =>
2631 configuration . ReadFrom . Configuration ( context . Configuration ) ) ;
@@ -89,6 +94,54 @@ public static void Run(string[] args)
8994 app . LoadAuthenticationProviders ( ) ;
9095 app . Run ( ) ;
9196 }
97+
98+ private static void AddTrustedProxies ( this ForwardedHeadersOptions options , string trustedProxies )
99+ {
100+ if ( string . IsNullOrWhiteSpace ( trustedProxies ) )
101+ return ;
102+ var proxies = trustedProxies . Split ( ',' , StringSplitOptions . RemoveEmptyEntries ) ;
103+
104+ foreach ( var proxy in proxies )
105+ {
106+ var trimmedProxy = proxy . Trim ( ) ;
107+ // Check if it's a CIDR block
108+ if ( trimmedProxy . Contains ( '/' ) )
109+ {
110+ if ( TryParseIpNetwork ( trimmedProxy , out var network , out var prefixLength ) )
111+ {
112+ options . KnownNetworks . Add ( new IPNetwork ( network , prefixLength ) ) ;
113+ }
114+ }
115+ // Single IP address
116+ else if ( IPAddress . TryParse ( trimmedProxy , out var ipAddress ) )
117+ {
118+ options . KnownProxies . Add ( ipAddress ) ;
119+ }
120+ }
121+ }
122+
123+ private static bool TryParseIpNetwork ( string cidr , out IPAddress network , out int prefixLength )
124+ {
125+ network = IPAddress . None ;
126+ prefixLength = 0 ;
127+
128+ var parts = cidr . Split ( '/' ) ;
129+ if ( parts . Length != 2 )
130+ return false ;
131+
132+ if ( ! IPAddress . TryParse ( parts [ 0 ] , out network ) )
133+ return false ;
134+
135+ if ( ! int . TryParse ( parts [ 1 ] , out prefixLength ) )
136+ return false ;
137+
138+ // Validate prefix length based on address family
139+ var maxPrefixLength = network . AddressFamily == AddressFamily . InterNetwork ? 32 : 128 ;
140+ if ( prefixLength < 0 || prefixLength > maxPrefixLength )
141+ return false ;
142+
143+ return true ;
144+ }
92145}
93146
94147internal sealed partial class SlugifyParameterTransformer : IOutboundParameterTransformer
0 commit comments