Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to HTTPS (SSL) with self-hosted ASP.NET Core 2 app (httpsys)

I wrote a little ASP.NET Core 2 application. It runs as a service, so no IIS. It runs on a PC with Windows 7 SP1.

var host = WebHost.CreateDefaultBuilder(args)
            .UseContentRoot(pathToContentRoot)
            .UseHttpSys(options =>
            {
                options.Authentication.Schemes = AuthenticationSchemes.None;
                options.Authentication.AllowAnonymous = true;
                options.MaxConnections = null;
                options.MaxRequestBodySize = 30000000;
                options.UrlPrefixes.Add("http://*:5050");
            })
            .UseStartup<Startup>()
            .UseApplicationInsights()
            .Build();

if (isService)
{
    host.RunAsService();
}
else
{
    host.Run();
} 

As you can see, I want to listen on port 5050. This is working fine without SSL.

My question is, how can I enable https for my application? Again: No IIS, no Domain-Name (no internet connection). Communication is just inside the internal network, so I want to use a self-signed certificate.

I read the documentation (HTTP.sys documentation;Netsh Commands;New-SelfSignedCertificate), but there is always something different to my situation (they use Krestel, or it is for using IIS). Also, I dont know how to get the App-ID (needed for netsh) for my Application. I tryed this: StackOverflow Get GUID but it doesn't work.

var assembly = typeof(Program).Assembly;

// following line produces: System.IndexOutOfRangeException
var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];

var id = attribute.Value;
Console.WriteLine(id);

So I am a bit confused about all the possabilitys and different configurations. And the docs don't consider my specific case.

I created a certificate, and I guess I need to store it on the "my" Store. (Where is that? cert:\LocalMachine\My) And then I need to assign my Applicaion ID and Port to it.

But I have no idea how to do that exactly. Can anyone help?

like image 778
Klatschen Avatar asked Aug 13 '18 13:08

Klatschen


1 Answers

So I solve the problem in the following way:

First, if you want to know your own GUID, you will get it with the following code:

var id = typeof(RuntimeEnvironment).GetTypeInfo().Assembly.GetCustomAttribute<GuidAttribute>().Value;

Create a SelfSigned Certificate

Now create a SelfSigned-Certificate (Skip this if you already got one, or purchased one)

  1. Run the following OpenSSL command to generate your private key and public certificate. Answer the questions and enter the Common Name when prompted.

openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem

  1. Combine your key and certificate in a PKCS#12 (P12) bundle:

openssl pkcs12 -inkey key.pem -in certificate.pem -export -out certificate.p12

Install the certificate on the client:

For Windows 8 and higher:

Add Certificate to Windows Cert Store with PowerShell

PS C:> $certpwd = ConvertTo-SecureString -String "passwort" -Force –AsPlainText

PS C:> Import-PfxCertificate –FilePath D:\data\cert\certificate.p12 cert:\localMachine\my -Password $certpwd

Get Fingerprint (Hash) of certificate

PS C:\WINDOWS\system32> dir Cert:\LocalMachine\my

Install certificate (replace Hash, IP and Port with your values)

PS C:\WINDOWS\system32> $guid = [guid]::NewGuid()

PS C:\WINDOWS\system32> $certHash = "A1D...B672E"

PS C:\WINDOWS\system32> $ip = "0.0.0.0"

PS C:\WINDOWS\system32> $port = "5050"

PS C:\WINDOWS\system32> "http add sslcert ipport=$($ip):$port certhash=$certHash appid={$guid}" | netsh

You are done.

For Windows 7

Add Certificate to Windows Cert Store (note: use .pem file for this operation, because .p12 file seems to be not supported from certutil)

.\certutil.exe -addstore -enterprise -f "Root" C:\lwe\cert\certificate.pem

If his line throws the following error:

SSL Certificate add failed, Error 1312 A specified logon session does not exist. It may already have been terminated.

You have to do the steps manually (please insert the .p12 file when doing it manually, not .pem) :

Run mmc.exe

  • Go to File-> Add/Remove Snap-In

  • Choose the Certificates snap-in.

  • Select Computer Account

  • Navigate to: Certificates (Local Computer)\Personal\Certificates

  • Right click the Certificates folder and choose All Tasks -> Import.

  • Follow the wizard instructions to select the certificate. Be sure you check the export checkbox during wizard.

To get the hash of yor certificate, run the Internet Explorer, press Alt + X and go to Internet Options -> Content -> Certificates. Search your certificate and read the hash.

Now you can run the same commands as for Windows 8+:

Install certificate (replace Hash, IP and Port with your values)

PS C:\WINDOWS\system32> $guid = [guid]::NewGuid()

PS C:\WINDOWS\system32> $certHash = "A1D...B672E"

PS C:\WINDOWS\system32> $ip = "0.0.0.0"

PS C:\WINDOWS\system32> $port = "5050"

PS C:\WINDOWS\system32> "http add sslcert ipport=$($ip):$port certhash=$certHash appid={$guid}" | netsh

Edit your Code

After all, you have to set the UrlPrefixes to https. So in your Program.cs file you need to have:

var host = WebHost.CreateDefaultBuilder(args)
            .UseContentRoot(pathToContentRoot)
            .UseHttpSys(options =>
            {
                options.Authentication.Schemes = AuthenticationSchemes.None;
                options.Authentication.AllowAnonymous = true;
                options.MaxConnections = null;
                options.MaxRequestBodySize = 30000000;
                options.UrlPrefixes.Add("https://*:5050");
            })
            .UseStartup<Startup>()
            .UseApplicationInsights()
            .Build();
like image 192
Klatschen Avatar answered Oct 14 '22 12:10

Klatschen