Kestrel should listen to http://localhost:50008
and https://localhost:50009
. The certificate should be loaded from an external source at startup (in this example it's just loaded from files). Unfortunately, it only works if loaded from appsettings.json
(as described in Built in way to configure HTTPS with certificate in kestrel server) and not if configured in code (as described in ASP.NET Core application setup production SSL certificate).
The certificate is issued by Letsencrypt (production, not staging) for *.mydomain.xyz
. The A record for www.mydomain.xyz
points to 127.0.0.1
.
Program.cs
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => Results.Ok("hello"));
app.Run();
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Debug"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"Https": {
"Url": "https://*:50009",
"Certificate": {
"Path": "C:\\Users\\myusername\\certs\\acme_certificate_pem.crt",
"KeyPath": "C:\\Users\\myusername\\certs\\acme_certificate_private_key_pem.key"
}
},
"Http": {
"Url": "http://*:50008"
}
}
}
}
debug output
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:50008
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://[::]:50009
curl
(browser also shows correct cert for *.mydomain.xyz)
$ curl http://www.mydomain.xyz:50008
"hello"
$ curl https://www.mydomain.xyz:50009
"hello"
Program.cs
var builder = WebApplication.CreateBuilder(args);
var certPath = "C:\\Users\\myusername\\certs\\acme_certificate_pem.crt";
var keyPath = "C:\\Users\\myusername\\certs\\acme_certificate_private_key_pem.key";
var certificate = X509Certificate2.CreateFromPemFile(certPath, keyPath);
builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
serverOptions.Listen(IPAddress.Any, 50008);
serverOptions.Listen(IPAddress.Any, 50009, listenOptions =>
{
listenOptions.UseHttps(certificate);
});
});
var app = builder.Build();
app.MapGet("/", () => Results.Ok("hello"));
app.Run();
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Debug"
}
}
}
debug output
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://0.0.0.0:50008
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://0.0.0.0:50009
curl
$ curl http://www.mydomain.xyz:50008
"hello"
$ curl https://www.mydomain.xyz:50009
curl: (35) schannel: failed to receive handshake, SSL/TLS connection failed
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
serverOptions.Listen(IPAddress.Any, 50008);
serverOptions.Listen(IPAddress.Any, 50009, listenOptions =>
{
listenOptions.UseHttps();
});
});
var app = builder.Build();
app.MapGet("/", () => Results.Ok("hello"));
app.Run();
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Debug"
}
}
}
debug output
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://0.0.0.0:50008
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://0.0.0.0:50009
curl
(uses development certificate, issued to localhost)
$ curl http://www.mydomain.xyz:50008
"hello"
$ curl https://www.mydomain.xyz::50009 -k
"hello"
$ curl https://www.mydomain.xyz::50009
curl: (60) schannel: SNI or certificate check failed: SEC_E_WRONG_PRINCIPAL (0x80090322) - Der Zielprinzipalname ist falsch.
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
Use .pfx
and it will work. The reason is a technical limitation of Windows.