1

I have a web server running on an IoT device, more specifically, on an ESP32.

This web server serves a website that is used for managing the device and can contain some sensitive information, hence I need to serve the website using HTTPS. The problem is that a client who uses our device will have to accept the usual error on their preferred browser since my SSL certificate is not signed by a trusted authority - it's self-signed.

To the best of my knowledge, I cannot get my certificate signed for an IP address of the web server because they only accept Domain names.

  • So what is the best way around this?

Any suggestions are greatly appreciated because I have hit a brick wall.

9
  • Is the web server accessed only from internal clients on the same LAN as the web server? Or, is the web server accessed from remote clients on the public internet?
    – mti2935
    Feb 8 at 17:41
  • 2
    If you could create a valid, signed certificate without going through any verification process from a Certificate Authority, then what would prevent malicious services from doing the same thing?
    – maerics
    Feb 8 at 17:44
  • What's stopping you from simply setting up a self-signed certificate and trusting it manually on the client?
    – user163495
    Feb 8 at 18:41
  • You can get a 'real' SSL/TLS cert for a public IP address that is registered to you (not just assigned temporarily from your ISP) but (1) not for free and (2) I expect those conditions aren't usually met for IoT. For more dupes see my answer at stackoverflow.com/questions/69499225/… Feb 9 at 2:12

2 Answers 2

2

Do not reuse the same certificate and private key on multiple devices. The private key can and will be extracted from the device. Even if you managed to install a valid & CA signed certificate, anyone would be able to mimic your server. A man-in-the-middle situation would be equally insecure compared to using plain HTTP or a self-signed certificate without manual validation of the fingerprint.

The correct way

Every IoT device having enough computing power should behave like this:

  1. During the initial setup (and at any point after), allow the user to decide the hostname of the device. It could default to the IP address of the device, which would be fine if the client chooses to use self-signed certificates.
  2. Create a random key for the individual device that isn't just derived from predictable variables, like the serial number or MAC address of the device. Neither stick with a static key for the device for its entire lifetime; generate a new one every time.
  3. Using the random key, create a self-signed certificate for the hostname.
  4. Allow the user to download a certificate signing request (CSR).
  5. The user can now sign the certificate in a way appropriate to their infrastructure, whether it's a local PKI or a public CA, using a FQDN of a (sub)domain they own.
  6. Allow the upload of this certificate. Validate it's still a pair of the private key and replace the self-signed certificate with it.
1

You can't.

You're essentially asking "I want the whole world to trust me that I control 192.168.1.100". If you could request that, then anyone could. Obviously, we don't want random people and organizations to gain arbitrary "trusted IPs" in local networks.

Your Options

The problem "I want people to be able to connect to my server in their local network" isn't new, so there have been plenty of solutions:

Just use HTTP

On an internal network, it is very unlikely that an attacker will be able to use a Man-in-the-Middle attack. After all, if an attacker can sniff and decrypt your local wireless traffic, they need to be physically close and have cracked your Wi-Fi encryption key.

Use a self-signed certificate

This is marginally better and trades one browser warning for another. A security-conscious user would then manually confirm that this self-signed certificate is trusted, which actually offers very good security. Or conversely, a regular user would just click "okay" on the warning and ignore it, which is basically the HTTP scenario again.

In essence, you're better off just using plain old HTTP and give users the option to create a new self-signed certificate on-the-fly.

8
  • Thank you for your answer. After going through some solutions I have seen online I would like to ask if the following is possible. Since I can set up a DNS server on my IoT device and we, as company, can prove ownership of our commercial website <ourwebsitename>.com, can I request a new certificate from a CA for a domain such as <ourwebsitename>.localdev.com and then use this certificate on my device?
    – lukecam95
    Feb 9 at 11:20
  • @lukecam95 Yes, you can absolutely get a certificate for a domain, which routes to an internal IP. The issue then becomes that you essentially force every user to use that specific IP. For instance, if you routed local.example.com to 192.168.1.100, then you would force every user to use a 192.168.1.0/24 network. Some prefer a 0.0/24 network, others prefer a 10.0.0.0/8 network or others. It also means users cannot buy two devices, since they would both resolve to the same IP. It really creates more issues than it solves.
    – user163495
    Feb 9 at 11:23
  • In our case the connection is a 1:1 - One mobile device of the user connected to the web server of the device. If the client purchases multiple devices, they will all have their own web server so I guess this sounds like the best option.
    – lukecam95
    Feb 9 at 11:27
  • 1
    How does Plex do this? You can type in app.plex.tv and it will connect to your local server. I know they use HTTPS and are able to get a certificate that works in any browser. This blog post explains a little: plex.tv/blog/… . But it just says they use some DNS magic to make it work.
    – Blake
    Feb 9 at 20:10
  • 1
    No, it looks like they register a custom subdomain for your local server and request a certificate via Let's Encrypt. For instance my local server is registered as 192-168-1-51.3930b65afce840e481f8d561b56a8cd5.plex.direct. Which you can look up and see that the ip address is 192.168.1.51. Which is the address of my local server. This all happens automatically. I never configured anything. It just works.
    – Blake
    Feb 10 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.