ASP.NET Core Reverse Proxy Support With HAProxy

  • Home
  • DevOps
  • ASP.NET Core Reverse Proxy Support With HAProxy
HAProxy & ASP.NET Core

I’ve recently worked on many APIs that were developed using .NET Core, ASP.NET Core 2.2 to be exact. A Microsoft Azure hosted Kubernetes cluster (AKS) is used to host the web app using HAProxy as an Ingress Controller.

Traffic was set to terminate at the load balancer (in this case HAProxy is my ingress controller on Kubernetes) rather than using SSL Passthrough. This meant traffic reached the web application over port 80, rather than origin port of 443.

The Problem…

HAProxy is reverse proxying the request from port 443 to 80 – this means the API thought all traffic was being served over port 80 (non-encrypted). This meant the web application was incorrectly generating URLs.

A good example of the problem was the login Redirect URL generated by the OpenID middleware. The middleware automatically generated the return redirect URL to use HTTP rather than HTTPS. (I assume more problems would have cropped up if I used helpers to create fully qualified URLs)

A Simple Solution…

Thankfully, HAProxy can send the widely used X-Forwarded-Proto header. This tells the application of the original protocol before it reversed proxied the request. For example, if the original request was served over https, we can pass that header down to the application.

If you’re using the supported HAProxy ingress controller for Kubernetes this header is automatically set. Alternatively, it’s as simple as setting the following in your HAProxy config file in your frontend:

acl from-https ssl_fc
http-request set-header X-Forwarded-Proto https if from-https

Once this is done, ASP.NET core just needs to know to look at this header, add the following code to your startup file (Under Configure Services):

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

This will set both the ForwardedFor (for identifying the users real IP address rather than your reverse proxy) and the ForwardedProto headers correctly.

Tags:

    Dan Horrocks-Burgess

    Software Developer by day, Disney lover by night.