aspnet / BasicMiddleware

[Archived] Basic middleware components for ASP.NET Core. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
169 stars 84 forks source link

RequireHeaderSymmetry + KnownNetworks + KnownProxies + LogDebug + private set = Lots of pain! #177

Closed cwe1ss closed 7 years ago

cwe1ss commented 7 years ago

I just tried to use the HttpOverrides middleware and went through a lot more pain than I had expected:

The application is hosted on a server in an Azure VNET (10.10.1.5). I'm using an Azure Application Gateway in front of it which sits in a separate subnet of the same VNET (10.10.3.4). I'd consider this a pretty common setup.

Being naive, I followed the samples and tried this - to my surprise, it didn't work:

app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.All });

After some digging, I finally found that Azure Application Gateway doesn't set the X-Forwarded-Host header. Next attempt:

app.UseForwardedHeaders(new ForwardedHeadersOptions { 
  ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
});

Again, no success. Now I've finally seen the warning log messages from before. That's why I've also added RequireHeaderSymmetry (I want the IP in as many cases as possible):

app.UseForwardedHeaders(new ForwardedHeadersOptions { 
  ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
  RequireHeaderSymmetry = false
});

But again, no success. After looking at the source, I've seen that there's a KnownProxies property. This didn't pop up in IntelliSense of the object initializer because it doesn't have a public setter.

var forwardedOptions = new ForwardedHeadersOptions
{
    RequireHeaderSymmetry = false,
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
};
forwardedOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardedOptions);

However, still no success. After digging further into the source code, I've seen that the middleware has some LogLevel=Debug outputs which I haven't seen because my minimum Log Level was "Information". This gave me an "Unknown proxy" message. No I realized that there's also a KnownNetworks property - not sure why I missed this before. After clearing this as well, I ended up with the following configuration which finally worked:

var forwardedOptions = new ForwardedHeadersOptions
{
    RequireHeaderSymmetry = false,
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
};
forwardedOptions.KnownNetworks.Clear();
forwardedOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardedOptions);

Of course, in hindsight I could have figured this out faster, but still I think that there are quite a few issues with the current default settings:

Your thoughts?

glennc commented 7 years ago

Related: https://github.com/aspnet/BasicMiddleware/issues/190 in that we need to doc this whole experience to avoid these issue. Also considering changing some defaults to not hit the failure cases as commonly.