Kestrelhttpserver: Running Kestrel Using HTTPS

Created on 14 Jul 2016  路  14Comments  路  Source: aspnet/KestrelHttpServer

This is my Program.cs:

public class Program
{
    public static void Main(string[] args)
    {
        var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("hosting.json", optional: true)
            .Build();

        var host = new WebHostBuilder()
            .UseConfiguration(config)
            .UseKestrel(
                options =>
                {
                    options.AddServerHeader = false;
                })
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();

        host.Run();
    }
}

This is my hosting.json file:

{
  "server.urls": "http://*:4000/;https://*:44300/"
}

However, I get the following errors when navigating to https://localhost:44300/:

info: Microsoft.AspNetCore.Server.Kestrel[17]
      Connection id "0HKTBNRCHTFR4" bad request data: "The input string contains non-ASCII or null characters."
Microsoft.AspNetCore.Server.Kestrel.BadHttpRequestException: The input string contains non-ASCII or null characters.
info: Microsoft.AspNetCore.Server.Kestrel[17]
Connection id "0HKTBNQ3OVHVS" bad request data: "Malformed request: MethodIncomplete"
Microsoft.AspNetCore.Server.Kestrel.BadHttpRequestException: Malformed request: MethodIncomplete

Most helpful comment

Turns out, I was able to use a custom certificate only when the following conditions were met:

  1. I had to choose dotnet run (.net core 1.x) instead of Use IISExpress option
    image
  2. I had to add the following code:
    .UseUrls("http://*:1025", "https://*:44354")
    to match the following configuration in applicationhost.config file for my web api
    image
    Please note that the last two entries are relevant _where subdomain of actual domain is used and the certificate in use, is an actual , valid server certificate issued against a proper domain name._
  3. I had to enter custom DNS entry in my local development windows machine
    (%windir%\system32\drivers\etc\host) for DNS spoofing.
    127.0.0.1 local.MyActualDomain.COM

The important bit really was this:
.UseUrls("http://*:1025", "https://*:44354")
and to
Not use IISExpress.

I thought I could make an actual certificate work while using IISExpress at the same time. It does not seem so. IISExpress forces VS to use *localhost-trusted-certificate even when the following code is set for WebHostBuilder*

var path = hostingEnvironment.ContentRootPath + @"\cert\MYDomain.COM.pfx";
                            options.UseHttps(path, "CertificatePassword")
                            .UseConnectionLogging();

My full code is as follows:

IHostingEnvironment hostingEnvironment = null;
var host = new WebHostBuilder()
    .UseConfiguration(configuration)
    .UseKestrel(
        options =>
        {
            options.AddServerHeader = false;

            if (hostingEnvironment.IsDevelopment())
            {
                var path = hostingEnvironment.ContentRootPath + @"\cert\MyDomain.COM.pfx";
                options.UseHttps(path, "CertificatePassword")
                .UseConnectionLogging();
            }
        })

    .UseContentRoot(Directory.GetCurrentDirectory())
    .ConfigureServices(
        services =>
        {
            hostingEnvironment = services
                .Where(x => x.ServiceType == typeof(IHostingEnvironment))
                .Select(x => (IHostingEnvironment)x.ImplementationInstance)
                .First();
        })

    .UseIISIntegration()
    .UseUrls("http://*:1025", "https://*:44354")
    .UseStartup<Startup>()
    .Build();

host.Run();

Result:
image

I hope this helps someone.

All 14 comments

Is it possible to use Kestrel without a certificate like it is with IIS Express? Purely for development purposes of course. I just want to click past any browser warnings.

Nope. Make yourself a self signed cert.

That makes me sad but there is probably a security reason for it.

If I want to make my app run with Full IIS, IIS Express or Kestrel, presumably, I only want to use the UseHttps Kestrel extension method when running under Kestrel. When running under IIS, I want to specify the certificate in the IIS dashboard. Correct? If so, how do I achieve that?

FYI: IIS Express is using a cert, it was just installed at the same time as IIS Express and pre-configured with an allowed port range.

Also, the UseHttps extension no-ops if you do not also register any https urls. This makes it safe to include even when running in IIS/Express.

Thanks @Tratcher, thats some solid info.

After installing VS 2017 Update 15.2, the following setting seems to be completely ignored

.UseKestrel(
                    options =>
                    {
                        // Do not add the Server HTTP header when using the Kestrel Web Server.
                        options.AddServerHeader = false;
                            //Yes we are in development mode.!!!
                        if (hostingEnvironment.IsDevelopment())
                        {
                            //Why does it ignore the custom valid SSL I have put here in the VS 2017 15.2 release?
                            //The same code was working fine before VS 2017 15.2 Update
                            //It has now started loading a localhost certificate even though
                            //I am explicitly loading custom valid SSL certificate here (See below)
                            //Actual cert name and password has been replaced with dummy values.
                            options.UseHttps("DevelopmentCertificate.pfx", "password");

                        }
                    })

Why does it ignore the custom valid SSL I have put here in the VS 2017 15.2 release?
The same code was working fine before VS 2017 15.2 Update
Visual Studio has now started loading a localhost certificate in the browser upon debugging.. even though I am explicitly loading custom valid SSL certificate here (See below)

Actual cert name and password has been replaced with dummy values in the above code for sample sharing purposes..

Please advise.
@RehanSaeed and others.
Thanks.

Turns out, I was able to use a custom certificate only when the following conditions were met:

  1. I had to choose dotnet run (.net core 1.x) instead of Use IISExpress option
    image
  2. I had to add the following code:
    .UseUrls("http://*:1025", "https://*:44354")
    to match the following configuration in applicationhost.config file for my web api
    image
    Please note that the last two entries are relevant _where subdomain of actual domain is used and the certificate in use, is an actual , valid server certificate issued against a proper domain name._
  3. I had to enter custom DNS entry in my local development windows machine
    (%windir%\system32\drivers\etc\host) for DNS spoofing.
    127.0.0.1 local.MyActualDomain.COM

The important bit really was this:
.UseUrls("http://*:1025", "https://*:44354")
and to
Not use IISExpress.

I thought I could make an actual certificate work while using IISExpress at the same time. It does not seem so. IISExpress forces VS to use *localhost-trusted-certificate even when the following code is set for WebHostBuilder*

var path = hostingEnvironment.ContentRootPath + @"\cert\MYDomain.COM.pfx";
                            options.UseHttps(path, "CertificatePassword")
                            .UseConnectionLogging();

My full code is as follows:

IHostingEnvironment hostingEnvironment = null;
var host = new WebHostBuilder()
    .UseConfiguration(configuration)
    .UseKestrel(
        options =>
        {
            options.AddServerHeader = false;

            if (hostingEnvironment.IsDevelopment())
            {
                var path = hostingEnvironment.ContentRootPath + @"\cert\MyDomain.COM.pfx";
                options.UseHttps(path, "CertificatePassword")
                .UseConnectionLogging();
            }
        })

    .UseContentRoot(Directory.GetCurrentDirectory())
    .ConfigureServices(
        services =>
        {
            hostingEnvironment = services
                .Where(x => x.ServiceType == typeof(IHostingEnvironment))
                .Select(x => (IHostingEnvironment)x.ImplementationInstance)
                .First();
        })

    .UseIISIntegration()
    .UseUrls("http://*:1025", "https://*:44354")
    .UseStartup<Startup>()
    .Build();

host.Run();

Result:
image

I hope this helps someone.

When running behind IIS you always use IIS's SSL and cert, Kestrel's SSL & cert are disabled.

@Tratcher Yes understood but I was not running behind IIS. I was stil working with Visual Studio and IISExpress on my development machine and wanted to use a proper SSL certificate (not a self signed one nor the one created by IISExpress itself).

@timematcher when I want to use a proper domain cert locally; I'll add a line in

C:\Windows\System32\drivers\etc\hosts for that domain that resolves to 127.0.0.1

e.g.

127.0.0.1 site.example.com

Then you can use https://site.example.com/ to access localhost in the browser with the domain certificate. Remember to comment out the line when you want connect to the actual domain otherwise you'll always be connecting to localhost.

@benaadams You are saying that only host entry should have been enough and there is no need to switch away from using IISExpress?

Are you saying that a host entry is enough and a custom certificate will work even with IISExpress?

@timematcher my comments apply to both IIS and IIS Express. Those certs cannot be configured in your app, they must be configured in netsh.exe.

Was this page helpful?
0 / 5 - 0 ratings