Search code examples
c#asp.net-core.net-corekestrel-http-serverkestrel

HTTPS redirection for specific port only (listening on mixed ports) with Kestrel


Using .NET Core 2.1, C#, Kestrel.

This is going to be a weird request but: I have an external URL of which requires to be HTTPS and an internal URL which is HTTP only.

I am wondering how I can redirect any traffic to HTTP on port 443 to HTTPS (staying on same port, 443); at the moment it stays on HTTP and dies a horrible death.

(Note: port 888 remains as HTTP and any traffic going to there needs to stay as insecure HTTP.)

I have it set up in Program.cs as so:

WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(options =>
        {
            options.Listen(IPAddress.Any, 443, opts=>
            {
                opts.UseHttps("mycert.pfx");
            });

            options.Listen(IPAddress.Any, 888);
        })
    .Build();

On Startup, I tried with Configure(IApplicationBuilder app...) app.UseHttpsRedirection();

But this resulted in ALL traffic on both ports being redirected to HTTPS which is a problem for 888 as there is no SSL cert for it!

Is there any way to redirect from HTTP to HTTPS depending on port I specify it for? Thanks


Solution

  • The middleware pipeline by default runs regardless of what endpoint is used to reach your application. So if you just do app.UseHttpsRedirection(), then the HTTPS redirection middleware will run for all your public endpoints.

    There is a mechanism using UseWhen that allows you to set up a conditional middleware pipeline, when middleware is only added in certain conditions. This would look like this:

    app.UseWhen(context => context.Request.Port == 888, httpApp =>
    {
        httpApp.UseHttpsRedirection();
    });
    

    However, in your situation, this won’t help: The problem is that on a single port, you can only ever host a single thing. So if you want to host your application with HTTPS on port 443, then it will only accept HTTPS there. If you try to connect using unsecure HTTP, then it will fail because it cannot perform the necessary handshake.

    What you would want to do here is host both HTTP and HTTPS on the same port but that simply does not work since there isn’t a mechanism to figure out whether a client wants to do HTTP or HTTPS before they are actually already attempted to establish either.

    So no, you cannot redirect HTTP on port 443 to HTTPS on port 443.