smtp4dev icon indicating copy to clipboard operation
smtp4dev copied to clipboard

Difficulty enabling https on web interface using LetsEncrypt cert

Open TooMuchBlue opened this issue 2 years ago • 1 comments

Smtp4Dev 3.1.4 (latest release at this writing) running on Windows Server 2016. In actual use I would be running as a service, and putting these settings into appsettings.json, but for testing I am running from the command line.

Original command line: Rnwood.Smtp4dev.exe --db=M:\Websites\smtp4dev\database\smtp4dev.db --baseappdatapath=M:\Websites\smtp4dev\settings --urls=http://*:8080 --hostname=foo.example.org

The SMTP server runs fine with TlsMode set to None. The web interface is accessible over http://foo.example.org:8080/. All expected.

I'm trying to enable https for the web interface because browsers will complain about anything not https. I don't really care about StartTls support, but I can enable it if it will help. The server already has LetsEncrypt certificates at a fixed location on the C: drive. For simplicity of testing I copied them to the baseappdatapath, but the error is the same if I provide the full path and filename.

Variation 1: Rnwood.Smtp4dev.exe --db=M:\Websites\smtp4dev\database\smtp4dev.db --baseappdatapath=M:\Websites\smtp4dev\settings --urls=https://*:8443 --hostname=foo.example.org --tlscertificate=cert.cer

Variation 2: Rnwood.Smtp4dev.exe --db=M:\Websites\smtp4dev\database\smtp4dev.db --baseappdatapath=M:\Websites\smtp4dev\settings --urls=https://*:8443 --hostname=foo.example.org --tlscertificate=cert.cer --tlscertificateprivatekey=cert.key

Variation 3: Rnwood.Smtp4dev.exe --db=M:\Websites\smtp4dev\database\smtp4dev.db --baseappdatapath=M:\Websites\smtp4dev\settings --urls=https://*:8443 --hostname=foo.example.org --tlscertificate=cert.pfx

Results 1-3:

... TLS mode: None SMTP Server is listening on port 25. Keeping last 100 messages and 100 sessions. IMAP Server is listening on port 143 Unable to start Kestrel. System.InvalidOperationException: Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date. To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'. For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054. at Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.UseHttps(ListenOptions listenOptions, Action``1 configureOptions) ...many lines omitted... at Rnwood.Smtp4dev.Program.Main(String[] args) in /home/vsts/work/1/s/Rnwood.Smtp4dev/Program.cs:line 51

My next thought was that maybe it would not properly load the certificate unless TlsMode was StartTls.

Variation 4: Rnwood.Smtp4dev.exe --db=M:\Websites\smtp4dev\database\smtp4dev.db --baseappdatapath=M:\Websites\smtp4dev\settings --urls=https://*:8443 --hostname=foo.example.org --tlsmode=StartTls --tlscertificate=cert.cer

Variation 5: Rnwood.Smtp4dev.exe --db=M:\Websites\smtp4dev\database\smtp4dev.db --baseappdatapath=M:\Websites\smtp4dev\settings --urls=https://*:8443 --hostname=foo.example.org --tlsmode=StartTls --tlscertificate=cert.cer --tlscertificateprivatekey=cert.key

Variation 6: Rnwood.Smtp4dev.exe --db=M:\Websites\smtp4dev\database\smtp4dev.db --baseappdatapath=M:\Websites\smtp4dev\settings --urls=https://*:8443 --hostname=foo.example.org --tlsmode=StartTls --tlscertificate=cert.pfx

Results 4-5: same error about No server certificate was specified

Result 6:

... TLS mode: StartTls The SMTP server failed to start: Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The specified network password is not correct. at Internal.Cryptography.Pal.CertificatePal.FilterPFXStore(Byte[] rawData, SafePasswordHandle password, PfxCertStoreFlags pfxCertStoreFlags) ... lines omitted ... at Rnwood.Smtp4dev.Server.CertificateHelper.LoadCertificate(String certificatePath, String password) in /home/vsts/work/1/s/Rnwood.Smtp4dev/Server/CertificateHelper.cs:line 30 at Rnwood.Smtp4dev.Server.Smtp4devServer.GetTlsCertificate() in /home/vsts/work/1/s/Rnwood.Smtp4dev/Server/Smtp4devServer.cs:line 98 at Rnwood.Smtp4dev.Server.Smtp4devServer.CreateSmtpServer() in /home/vsts/work/1/s/Rnwood.Smtp4dev/Server/Smtp4devServer.cs:line 61 at Rnwood.Smtp4dev.Server.Smtp4devServer.TryStart() in /home/vsts/work/1/s/Rnwood.Smtp4dev/Server/Smtp4devServer.cs:line 396 ... network password error lines repeat ... IMAP Server is listening on port 143 Unable to start Kestrel. System.InvalidOperationException: Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date. ... same error as Variations 1-5 again ...

This at least confirmed that it is correctly looking in baseappdatapath. I looked at the history for CertificateHelper and discovered that the --tlscertificatepassword was not supported in this version, so I won't be able to fix the password for PFX.

But why is it unable to parse the cer/key files? I confirmed that the cer and key files are in PEM format, as expected in CertificateHelper. Both files are using 0x0A for line endings. I see that #920 was merged before this build, so support for the key file is apparently included.

I would hope that if there was something wrong with the keys (file permission, not PEM format, keys aren't related), it would give some error message about "provided keys are unusable" instead of just crashing with a stack dump.

I saw another ticket from a couple of years ago (sorry, can't find it now) that talked about improving the docs around TLS configuration. I would definitely be willing to contribute to that effort.

One more variation worth mentioning, Variation 7: Rnwood.Smtp4dev.exe --db=M:\Websites\smtp4dev\database\smtp4dev.db --baseappdatapath=M:\Websites\smtp4dev\settings --urls=https://*:8443 --hostname=foo.example.org --tlsmode=StartTls

In this case, SMTP is able to run in StartTls using the self-signed certificate, but Kestrel still fails with the same error as results 1-5. Shouldn't the app know to pass the self-signed certificate over to Kestrel, or would it be more appropriate to have separate configurations for a certificate for the web interface?

Let me know if I can provide more information, or where I can start to contribute.

TooMuchBlue avatar Aug 26 '22 17:08 TooMuchBlue

For what I get after a quick, superficial look at the code, the --tlsmode and --hostname command line arguments and their respective appsettings.json counterparts only affect the configuration of the SMTP listening port i.e. 25 by default. To get the web interface running with https you need to combine the --urls command line argument with environment variables to set the certificate.

SET ASPNETCORE_Kestrel:Certificates:Default:Path=certificate.pfx
SET ASPNETCORE_Kestrel:Certificates:Default:Password=yourCertificatePassword
Rnwood.Smtp4dev.exe --db=M:\Websites\smtp4dev\database\smtp4dev.db --baseappdatapath=M:\Websites\smtp4dev\settings --urls=https://*:8443

I haven't actually tested this in Windows, but I have it working using a Linux Docker container.

miguel-rodriguez-cimino avatar Jul 12 '23 21:07 miguel-rodriguez-cimino

Thanks for the feedback around confusion about what TLSMODE and HOSTNAME settings apply to. I have updated this so it's clear.

Keeping this ticket open to document/improve HTTPS setup for the web interface.

rnwood avatar Apr 25 '24 18:04 rnwood