smtp4dev
smtp4dev copied to clipboard
Difficulty enabling https on web interface using LetsEncrypt cert
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.
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.
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.