Home icon indicating copy to clipboard operation
Home copied to clipboard

WebServer Running HTTPS

Open renerlemes opened this issue 8 months ago • 15 comments

Library/API/IoT binding

nanoFramework.WebServer

Visual Studio version

No response

.NET nanoFramework extension version

No response

Target name(s)

ESP32_S3_ALL

Firmware version

Latest

Device capabilities

No response

Description

When I'm using WebServer on port 80 with HTTP, everything works normally, but when I use the example itself that is in the repository (https://github.com/nanoframework/Samples/blob/main/samples/Webserver/WebServer.Sample/WebServer.Sample/Program.cs), I receive some errors. I also tried generating new certificates and the problem persists.

A VERY IMPORTANT detail is that I receive the ECONNRESET message only after I start an MQTT connection with SSL using another certificate. If start without certificate and segure connection works.

How to reproduce

        private const string _myWebServerCrt =
@"-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----";

        private const string _myWebServerPrivateKey =
@"-----BEGIN RSA PRIVATE KEY-----

-----END RSA PRIVATE KEY-----";

X509Certificate _myWebServerCertificate509 = new X509Certificate2(_myWebServerCrt, _myWebServerPrivateKey, "1234");

nanoFramework.WebServer.WebServer webServer = new nanoFramework.WebServer.WebServer(443, HttpProtocol.Https, types)
{
    HttpsCert = _myWebServerCertificate509,

    SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13
};

webServer.Start()

The code used for MQTTS is:

string s_certificate =
@"-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----";
X509Certificate caCert = new(s_certificate);

MqttClient mqttClient = new("broker.emqx.io", 8883, true, caCert, null, MqttSslProtocols.TLSv1_2);

MqttReasonCode status = mqttClient.Connect(Core.Configuration.Configs.Dispositivo.Serial, "device", "123456");

When any webserver endpoint is called, the below error is displayed

++++ Exception System.Net.Sockets.SocketException - CLR_E_FAIL (5) ++++
++++ Message: 
++++ System.Net.Security.SslNative::SecureServerInit [IP: 0000] ++++
++++ System.Net.Security.SslStream::Authenticate [IP: 0024] ++++
++++ System.Net.Security.SslStream::AuthenticateAsServer [IP: 0016] ++++
++++ System.Net.HttpListener::AcceptThreadFunc [IP: 009a] ++++

Image

Expected behaviour

No response

Screenshots

Make it possible to receive HTTPS requests

Sample project or code

No response

Aditional information

No response

renerlemes avatar Jun 27 '25 18:06 renerlemes

@renerlemes , is the date and time on the ESP32 correct?

alberk8 avatar Jun 30 '25 07:06 alberk8

Just to male it sure I understand correctly:

  • You have 1 certificate for the WebServer using HTTPS
  • You have 1 certificate for MQTTS
    • The 2 certificates are different

If you are using one of the other, everything works fine, the problem is when you have both. Is that a good understanding of the situation?

Ellerbach avatar Jun 30 '25 09:06 Ellerbach

Just to male it sure I understand correctly:

  • You have 1 certificate for the WebServer using HTTPS
  • You have 1 certificate for MQTTS
    • The 2 certificates are different

If you are using one of the other, everything works fine, the problem is when you have both. Is that a good understanding of the situation?

@Ellerbach, yes, that is exactly what is happening! Can you imagine what it could be or have you ever experienced this problem?

renerlemes avatar Jun 30 '25 09:06 renerlemes

@renerlemes Can you confirm that each part is individually working fine? And that it's only when you have both that it's not working?

Ellerbach avatar Jul 03 '25 09:07 Ellerbach

@Ellerbach Each part works fine individually. If I use only MQTTS or only the WebServer with HTTPS, they work without any problems. But if I start both with their respective certificates, HTTPS displays the error I reported.

I'm going to create a very simple code to connect to the wireless network, and I'll create the MQTTS and Webserver connections with HTTPS just to confirm once again and I'll let you know.

renerlemes avatar Jul 03 '25 12:07 renerlemes

I was just reading this again and it stroke me: I'm not sure if the mbedTLS API is prepared to handle two different server certificates... Almost sure our API isn't. I mean, there a single execution path for the SSL that at some point setups the server cert. I don't think it was ever foreseen the need to have different server certs depending on the endpoint.

Wondering why can't you use the same server cert for both scenarios?

josesimoes avatar Jul 03 '25 13:07 josesimoes

@renerlemes can you try to place both certs in the cert section? as far as I remember, mbeds can handle multiple certs but also, they should be able to be uploaded at the same time otherwise one will replace the other one. In sort, put both together, copy/paste both section together and check if still works individually and then if works together.

Ellerbach avatar Jul 03 '25 13:07 Ellerbach

@josesimoes It is not possible to use the same certificate, because one is for connecting to MQTTS, where I am currently using the EMQX broker. They already provide the certificate for connection. The certificate used for the WebServer with HTTPS is generated as a self-signed certificate. Therefore, they are certificates with different purposes.

@Ellerbach How to add both certificates in the certificates section? It would look something like this:

CertificateManager.AddCaCertificateBundle(new X509Certificate[] { caCert });

I did it the way I said above and anyway, when using the certificate, I need to create a certificate with new X509Certificate(s_certificate);

I adjusted the code in my first post to display the WebServer and MQTT part. Another important observation is that the WebServer with HTTPS and MQTTS starts without errors, only when I use any endpoint does the error appear.

renerlemes avatar Jul 03 '25 18:07 renerlemes

Of course they are! The one you use to connect to mqtt is a device cert. You use it to authenticate with the server. When you start a local Webserver you can include a server cert. Which, if I'm not mistaken "goes" into the same place as the other, because it's also a device cert (the server is your device).

Unlike the root CA cert, for which you can bundle as many as you want, you cannot do that for device certs. A device can only present one cert when it's requested during the auth negotiation.

Let me refrase the question:why do you need to offer secure access to your Webserver?

josesimoes avatar Jul 03 '25 18:07 josesimoes

I tested using the same certificate and it didn't work either.

Regarding your question, I need to use secure access, because I have a web page that connects to the device's IP when it is in AP Mode and performs the necessary configurations for it to work the way I need it to.

For security reasons, browsers do not allow a connection between HTTPS (configuration page) and HTTP (my device's webserver).

Of course, I could change the part of my configuration page to run HTTP, but most hosting services no longer allow it without a security certificate.

renerlemes avatar Jul 03 '25 18:07 renerlemes

But, because you're using a self signed cert, you still have the problem of making the browser to trust that connection and cert.

josesimoes avatar Jul 03 '25 21:07 josesimoes

I was using Postman for testing and now I realized that it was ignoring the certificate. There really won't be any way to use the webserver with HTTPS, because as it is in a local environment, there is no way to generate a valid and trusted certificate (as far as I know)

renerlemes avatar Jul 04 '25 11:07 renerlemes

I was using Postman for testing and now I realized that it was ignoring the certificate. There really won't be any way to use the webserver with HTTPS, because as it is in a local environment, there is no way to generate a valid and trusted certificate (as far as I know)

If you own a domain, then you can generate a site or wildcard certificate with LetsEncrypt for free (need to renew every 3 months). The certificate will be valid for online or offline use.

alberk8 avatar Jul 05 '25 00:07 alberk8

You need to have a public domain to generate a valid SSL certificate. Even using mDNS as an alternative, it would still not be possible

renerlemes avatar Jul 05 '25 00:07 renerlemes

@renerlemes you can add the certs one after the the other one like this:

    private const string _myCerts =

@"-----BEGIN CERTIFICATE----- DATAFORFIRSTCERT -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- DATAFORSECONDCERT -----END CERTIFICATE-----";

That should work fine

Ellerbach avatar Jul 06 '25 11:07 Ellerbach