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.

Esa Jokinen
  • 16,100
  • 5
  • 50
  • 55
lukecam95
  • 13
  • 1
  • 3
  • 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 08 '22 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 08 '22 at 17:44
  • Related: https://security.stackexchange.com/questions/121163/how-do-i-run-proper-https-on-an-internal-network – mti2935 Feb 08 '22 at 18:18
  • What's stopping you from simply setting up a self-signed certificate and trusting it manually on the client? –  Feb 08 '22 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 https://stackoverflow.com/questions/69499225/how-to-solve-the-problem-of-self-signed-ssl-certificates-for-sites-intended – dave_thompson_085 Feb 09 '22 at 02:12
  • @mti2935 The web server will only be accessed on its own LAN by clients using whichever device they prefer, such as their mobile phone. – lukecam95 Feb 09 '22 at 07:53
  • @maerics Good point. There is no ideal way to do this it seems, however I need the best possible solution while keeping security and user experience in mind. – lukecam95 Feb 09 '22 at 07:54
  • @MechMK1 I don't have control over the clients devices. The product will be sold around the world to many different clients and hence I need a long lasting or an automated solution. – lukecam95 Feb 09 '22 at 07:54
  • @dave_thompson_085 As you say, Public IP address for this scenario would be too expensive. Thanks for the links ,there are a some good discussions there. – lukecam95 Feb 09 '22 at 07:54

2 Answers2

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.
Esa Jokinen
  • 16,100
  • 5
  • 50
  • 55
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.

  • 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 .com, can I request a new certificate from a CA for a domain such as .localdev.com and then use this certificate on my device? – lukecam95 Feb 09 '22 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. –  Feb 09 '22 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 09 '22 at 11:27
  • @lukecam95 As I said, in this case, you're best off just using plain HTTP and offering HTTPS for advanced users. –  Feb 09 '22 at 11:50
  • 1
    How does Plex do this? You can type in https://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: https://www.plex.tv/blog/its-not-easy-being-green-secure-communication-arrives/ . But it just says they use some DNS magic to make it work. – Blake Feb 09 '22 at 20:10
  • @Blake that "DNS magic" is likely tunneling (ngrok, localtunnel, telebit, etc). theyre using their primary domain that is recognized by a CA and can use a different security method behind the scenes. – Tonithy Feb 10 '22 at 01:33
  • 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 '22 at 14:05
  • @Blake thats cool. i remember it taking a bit of time to provision with LetsEncrypt, but now im seeing the process go in seconds with certbot – Tonithy Feb 10 '22 at 19:29