A Singapore Government Agency Website

ASP.NET Core with Container Stack Ingress SSL Termination

Reference: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-6.0

Extract:

In the recommended configuration for ASP.NET Core, the app is hosted using ASP.NET Core Module (ANCM) for IIS, Nginx, or Apache. Proxy servers, load balancers, and other network appliances often obscure information about the request before it reaches the app:

When HTTPS requests are proxied over HTTP, the original scheme (HTTPS) is lost and must be forwarded in a header.

Because an app receives a request from the proxy and not its true source on the Internet or corporate network, the originating client IP address must also be forwarded in a header.

This information may be important in request processing, for example in redirects, authentication, link generation, policy evaluation, and client geolocation.

For ASP.NET Core applications to work behind an SSL-terminated proxy, it is important that Forwarded Headers Middleware is configured.

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders =
        ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});

var app = builder.Build();
app.UseForwardedHeaders();

app.Run();

In Container Stack, the SSL terminates at the Ingress, and the forward information are passed as headers to the upstream services. However, X-Forwarded-Proto is not forwarded due to the way ingress is configured.

As a workaround, ASP.NET Core applications will need to configure an alternative header to check for the protocol.

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedProtoHeaderName = "X-Forwarded-Proto-CS";
});

var app = builder.Build();
app.UseForwardedHeaders();

app.Run();

The new custom header will need to be injected into the upstream service, to inform ASP.NET of the correct protocol to use. This is done via KongPlugin on the Ingress.

---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: customkongplugin
config: 
  add:
    headers:
    - "X-Forwarded-Proto-CS: https"
plugin: request-transformer
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myingress
  annotations:
    konghq.com/plugins: customkongplugin
spec:
  ingressClassName: kong
--- snip ---

Once this is done, the upstream ASP.NET core application will use https as the request scheme (even though it is listening on a non-https port).

Chat with me!
Bot Launcher