Skip to content
This repository was archived by the owner on Dec 20, 2018. It is now read-only.
This repository was archived by the owner on Dec 20, 2018. It is now read-only.

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

Closed
@cwe1ss

Description

@cwe1ss

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:

  • The original IP is REALLY important.: IMO it's better to set a value, even if the headers don't match. Just ignoring the IP and keeping the proxy IP leaves one completely blind. So I don't think, RequireHeaderSymmetry should be true by default. What's the benefit with this?
  • KnownProxies/KnownNetworks could be made more discoverable by making it public set to use it in the object initializer.
  • "Unknown proxy" is a pretty interesting message. My app is running in an internal network so every occurence of this is at least "informational".
  • Very few people run a proxy on 127.0.0.1 or ::1. Limiting the middleware to localhost is very weird. Also, it's not documented that these are added by default. Why isn't this opt-in? If this should be a security measure to prevent unintended access, why not block the request completely? What's the point in just ignoring the value?
  • The code I ended up with is far from simple/reusable. We have multiple applications which need this setup. Would have been nicer if this was covered by the defaults.

Your thoughts?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions